Skip to content

Commit

Permalink
Merge pull request moby#5 from rtyler/current-17.05
Browse files Browse the repository at this point in the history
Forward-porting changes for FreeBSD on v17.05.0-ce
  • Loading branch information
R. Tyler Croy committed Sep 4, 2017
2 parents 0626df2 + 25cb15b commit 9648f08
Show file tree
Hide file tree
Showing 55 changed files with 2,674 additions and 275 deletions.
10 changes: 10 additions & 0 deletions Jenkinsfile
@@ -0,0 +1,10 @@
pipeline {
agent { label 'freebsd' }
stages {
stage('Build') {
steps {
sh 'AUTO_GOPATH=1 ./hack/make.sh binary'
}
}
}
}
10 changes: 0 additions & 10 deletions container/container_notlinux.go
Expand Up @@ -11,13 +11,3 @@ func detachMounted(path string) error {
// Therefore there are separate definitions for this.
return unix.Unmount(path, 0)
}

// SecretMount returns the mount for the secret path
func (container *Container) SecretMount() *Mount {
return nil
}

// UnmountSecrets unmounts the fs for secrets
func (container *Container) UnmountSecrets() error {
return nil
}
9 changes: 9 additions & 0 deletions daemon/container_freebsd.go
@@ -0,0 +1,9 @@
package daemon

import (
"github.com/docker/docker/container"
)

func (daemon *Daemon) saveApparmorConfig(container *container.Container) error {
return nil
}
44 changes: 44 additions & 0 deletions daemon/container_operations_freebsd.go
@@ -0,0 +1,44 @@
package daemon

import (
"github.com/docker/docker/container"
"github.com/docker/docker/runconfig"
"github.com/docker/libnetwork"
)

func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]string, error) {
return nil, nil
}

func (daemon *Daemon) setupIpcDirs(container *container.Container) error {
return nil
}

func killProcessDirectly(container *container.Container) error {
return nil
}

func detachMounted(path string) error {
return nil
}

func isLinkable(child *container.Container) bool {
// A container is linkable only if it belongs to the default network
_, ok := child.NetworkSettings.Networks[runconfig.DefaultDaemonNetworkMode().NetworkName()]
return ok
}

func enableIPOnPredefinedNetwork() bool {
return false
}

func (daemon *Daemon) isNetworkHotPluggable() bool {
return false
}

func setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error {
return nil
}

func initializeNetworkingPaths(container *container.Container, nc *container.Container) {
}
@@ -1,4 +1,4 @@
// +build linux freebsd
// +build linux

package daemon

Expand Down
2 changes: 0 additions & 2 deletions daemon/container_operations_solaris.go
@@ -1,5 +1,3 @@
// +build solaris

package daemon

import (
Expand Down
37 changes: 37 additions & 0 deletions daemon/daemon_freebsd.go
@@ -0,0 +1,37 @@
package daemon

import (
"github.com/docker/libnetwork"
"github.com/docker/docker/api/types"
"github.com/docker/docker/container"
"github.com/docker/docker/daemon/config"
)
func getPluginExecRoot(root string) string {
return "/run/docker/plugins"
}

func (daemon *Daemon) cleanupMountsByID(id string) error {
return nil
}

// cleanupMounts umounts shm/mqueue mounts for old containers
func (daemon *Daemon) cleanupMounts() error {
return nil
}

func initBridgeDriver(controller libnetwork.NetworkController, config *config.Config) error {
// TODO
return nil
}

func removeDefaultBridgeInterface() {
}

func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
s := &types.StatsJSON{}
return s, nil
}

func (daemon *Daemon) initCgroupsPath(path string) error {
return nil
}
240 changes: 240 additions & 0 deletions daemon/daemon_linux.go
Expand Up @@ -10,6 +10,11 @@ import (

"github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/mount"
"github.com/docker/libnetwork/drivers/bridge"
"github.com/docker/docker/api/types"
"github.com/golang/protobuf/ptypes"
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/vishvananda/netlink"
)

// On Linux, plugins use a static path for storing execution state,
Expand Down Expand Up @@ -86,3 +91,238 @@ func getCleanPatterns(id string) (regexps []*regexp.Regexp) {
}
return
}

func initBridgeDriver(controller libnetwork.NetworkController, config *config.Config) error {
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.EnableIPMasquerade: strconv.FormatBool(config.BridgeConfig.EnableIPMasq),
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
ipamV6Conf *libnetwork.IpamConf
)

ipamV4Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)}

nwList, nw6List, 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()
}

var deferIPv6Alloc bool
if config.BridgeConfig.FixedCIDRv6 != "" {
_, fCIDRv6, err := net.ParseCIDR(config.BridgeConfig.FixedCIDRv6)
if err != nil {
return err
}

// In case user has specified the daemon flag --fixed-cidr-v6 and the passed network has
// at least 48 host bits, we need to guarantee the current behavior where the containers'
// IPv6 addresses will be constructed based on the containers' interface MAC address.
// We do so by telling libnetwork to defer the IPv6 address allocation for the endpoints
// on this network until after the driver has created the endpoint and returned the
// constructed address. Libnetwork will then reserve this address with the ipam driver.
ones, _ := fCIDRv6.Mask.Size()
deferIPv6Alloc = ones <= 80

if ipamV6Conf == nil {
ipamV6Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)}
}
ipamV6Conf.PreferredPool = fCIDRv6.String()

// In case the --fixed-cidr-v6 is specified and the current docker0 bridge IPv6
// address belongs to the same network, we need to inform libnetwork about it, so
// that it can be reserved with IPAM and it will not be given away to somebody else
for _, nw6 := range nw6List {
if fCIDRv6.Contains(nw6.IP) {
ipamV6Conf.Gateway = nw6.IP.String()
break
}
}
}

if config.BridgeConfig.DefaultGatewayIPv6 != nil {
if ipamV6Conf == nil {
ipamV6Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)}
}
ipamV6Conf.AuxAddresses["DefaultGatewayIPv6"] = config.BridgeConfig.DefaultGatewayIPv6.String()
}

v4Conf := []*libnetwork.IpamConf{ipamV4Conf}
v6Conf := []*libnetwork.IpamConf{}
if ipamV6Conf != nil {
v6Conf = append(v6Conf, ipamV6Conf)
}
// Initialize default network on "bridge" with the same name
_, err = controller.NewNetwork("bridge", "bridge", "",
libnetwork.NetworkOptionEnableIPv6(config.BridgeConfig.EnableIPv6),
libnetwork.NetworkOptionDriverOpts(netOption),
libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil),
libnetwork.NetworkOptionDeferIPv6Alloc(deferIPv6Alloc))
if err != nil {
return fmt.Errorf("Error creating default \"bridge\" network: %v", err)
}
return nil
}


// Remove default bridge interface if present (--bridge=none use case)
func removeDefaultBridgeInterface() {
if lnk, err := netlink.LinkByName(bridge.DefaultBridgeName); err == nil {
if err := netlink.LinkDel(lnk); err != nil {
logrus.Warnf("Failed to remove bridge interface (%s): %v", bridge.DefaultBridgeName, err)
}
}
}

func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
if !c.IsRunning() {
return nil, errNotRunning{c.ID}
}
stats, err := daemon.containerd.Stats(c.ID)
if err != nil {
return nil, err
}
s := &types.StatsJSON{}
cgs := stats.CgroupStats
if cgs != nil {
s.BlkioStats = types.BlkioStats{
IoServiceBytesRecursive: copyBlkioEntry(cgs.BlkioStats.IoServiceBytesRecursive),
IoServicedRecursive: copyBlkioEntry(cgs.BlkioStats.IoServicedRecursive),
IoQueuedRecursive: copyBlkioEntry(cgs.BlkioStats.IoQueuedRecursive),
IoServiceTimeRecursive: copyBlkioEntry(cgs.BlkioStats.IoServiceTimeRecursive),
IoWaitTimeRecursive: copyBlkioEntry(cgs.BlkioStats.IoWaitTimeRecursive),
IoMergedRecursive: copyBlkioEntry(cgs.BlkioStats.IoMergedRecursive),
IoTimeRecursive: copyBlkioEntry(cgs.BlkioStats.IoTimeRecursive),
SectorsRecursive: copyBlkioEntry(cgs.BlkioStats.SectorsRecursive),
}
cpu := cgs.CpuStats
s.CPUStats = types.CPUStats{
CPUUsage: types.CPUUsage{
TotalUsage: cpu.CpuUsage.TotalUsage,
PercpuUsage: cpu.CpuUsage.PercpuUsage,
UsageInKernelmode: cpu.CpuUsage.UsageInKernelmode,
UsageInUsermode: cpu.CpuUsage.UsageInUsermode,
},
ThrottlingData: types.ThrottlingData{
Periods: cpu.ThrottlingData.Periods,
ThrottledPeriods: cpu.ThrottlingData.ThrottledPeriods,
ThrottledTime: cpu.ThrottlingData.ThrottledTime,
},
}
mem := cgs.MemoryStats.Usage
s.MemoryStats = types.MemoryStats{
Usage: mem.Usage,
MaxUsage: mem.MaxUsage,
Stats: cgs.MemoryStats.Stats,
Failcnt: mem.Failcnt,
Limit: mem.Limit,
}
// if the container does not set memory limit, use the machineMemory
if mem.Limit > daemon.machineMemory && daemon.machineMemory > 0 {
s.MemoryStats.Limit = daemon.machineMemory
}
if cgs.PidsStats != nil {
s.PidsStats = types.PidsStats{
Current: cgs.PidsStats.Current,
}
}
}
s.Read, err = ptypes.Timestamp(stats.Timestamp)
if err != nil {
return nil, err
}
return s, nil
}

func (daemon *Daemon) initCgroupsPath(path string) error {
if path == "/" || path == "." {
return nil
}

if daemon.configStore.CPURealtimePeriod == 0 && daemon.configStore.CPURealtimeRuntime == 0 {
return nil
}

// Recursively create cgroup to ensure that the system and all parent cgroups have values set
// for the period and runtime as this limits what the children can be set to.
daemon.initCgroupsPath(filepath.Dir(path))

mnt, root, err := cgroups.FindCgroupMountpointAndRoot("cpu")
if err != nil {
return err
}
// When docker is run inside docker, the root is based of the host cgroup.
// Should this be handled in runc/libcontainer/cgroups ?
if strings.HasPrefix(root, "/docker/") {
root = "/"
}

path = filepath.Join(mnt, root, path)
sysinfo := sysinfo.New(true)
if err := maybeCreateCPURealTimeFile(sysinfo.CPURealtimePeriod, daemon.configStore.CPURealtimePeriod, "cpu.rt_period_us", path); err != nil {
return err
}
if err := maybeCreateCPURealTimeFile(sysinfo.CPURealtimeRuntime, daemon.configStore.CPURealtimeRuntime, "cpu.rt_runtime_us", path); err != nil {
return err
}
return nil
}

0 comments on commit 9648f08

Please sign in to comment.