зеркало из https://github.com/microsoft/docker.git
189 строки
4.7 KiB
Go
189 строки
4.7 KiB
Go
package daemon
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
"sort"
|
|
"strconv"
|
|
|
|
containertypes "github.com/docker/docker/api/types/container"
|
|
"github.com/docker/docker/container"
|
|
"github.com/docker/docker/oci"
|
|
"github.com/docker/libnetwork"
|
|
"github.com/opencontainers/runtime-spec/specs-go"
|
|
)
|
|
|
|
func setResources(s *specs.Spec, r containertypes.Resources) error {
|
|
mem := getMemoryResources(r)
|
|
s.Solaris.CappedMemory = &mem
|
|
|
|
capCPU := getCPUResources(r)
|
|
s.Solaris.CappedCPU = &capCPU
|
|
|
|
return nil
|
|
}
|
|
|
|
func setUser(s *specs.Spec, c *container.Container) error {
|
|
uid, gid, additionalGids, err := getUser(c, c.Config.User)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s.Process.User.UID = uid
|
|
s.Process.User.GID = gid
|
|
s.Process.User.AdditionalGids = additionalGids
|
|
return nil
|
|
}
|
|
|
|
func getUser(c *container.Container, username string) (uint32, uint32, []uint32, error) {
|
|
return 0, 0, nil, nil
|
|
}
|
|
|
|
func (daemon *Daemon) getRunzAnet(ep libnetwork.Endpoint) (specs.Anet, error) {
|
|
var (
|
|
linkName string
|
|
lowerLink string
|
|
defRouter string
|
|
)
|
|
|
|
epInfo := ep.Info()
|
|
if epInfo == nil {
|
|
return specs.Anet{}, fmt.Errorf("invalid endpoint")
|
|
}
|
|
|
|
nw, err := daemon.GetNetworkByName(ep.Network())
|
|
if err != nil {
|
|
return specs.Anet{}, fmt.Errorf("Failed to get network %s: %v", ep.Network(), err)
|
|
}
|
|
|
|
// Evaluate default router, linkname and lowerlink for interface endpoint
|
|
switch nw.Type() {
|
|
case "bridge":
|
|
defRouter = epInfo.Gateway().String()
|
|
linkName = "net0" // Should always be net0 for a container
|
|
|
|
// TODO We construct lowerlink here exactly as done for solaris bridge
|
|
// initialization. Need modular code to reuse.
|
|
options := nw.Info().DriverOptions()
|
|
nwName := options["com.docker.network.bridge.name"]
|
|
lastChar := nwName[len(nwName)-1:]
|
|
if _, err = strconv.Atoi(lastChar); err != nil {
|
|
lowerLink = nwName + "_0"
|
|
} else {
|
|
lowerLink = nwName
|
|
}
|
|
|
|
case "overlay":
|
|
defRouter = ""
|
|
linkName = "net1"
|
|
|
|
// TODO Follows generateVxlanName() in solaris overlay.
|
|
id := nw.ID()
|
|
if len(nw.ID()) > 12 {
|
|
id = nw.ID()[:12]
|
|
}
|
|
lowerLink = "vx_" + id + "_0"
|
|
}
|
|
|
|
runzanet := specs.Anet{
|
|
Linkname: linkName,
|
|
Lowerlink: lowerLink,
|
|
Allowedaddr: epInfo.Iface().Address().String(),
|
|
Configallowedaddr: "true",
|
|
Defrouter: defRouter,
|
|
Linkprotection: "mac-nospoof, ip-nospoof",
|
|
Macaddress: epInfo.Iface().MacAddress().String(),
|
|
}
|
|
|
|
return runzanet, nil
|
|
}
|
|
|
|
func (daemon *Daemon) setNetworkInterface(s *specs.Spec, c *container.Container) error {
|
|
var anets []specs.Anet
|
|
|
|
sb, err := daemon.netController.SandboxByID(c.NetworkSettings.SandboxID)
|
|
if err != nil {
|
|
return fmt.Errorf("Could not obtain sandbox for container")
|
|
}
|
|
|
|
// Populate interfaces required for each endpoint
|
|
for _, ep := range sb.Endpoints() {
|
|
runzanet, err := daemon.getRunzAnet(ep)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to get interface information for endpoint %d: %v", ep.ID(), err)
|
|
}
|
|
anets = append(anets, runzanet)
|
|
}
|
|
|
|
s.Solaris.Anet = anets
|
|
if anets != nil {
|
|
s.Solaris.Milestone = "svc:/milestone/container:default"
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container) error {
|
|
linkedEnv, err := daemon.setupLinkedContainers(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s.Root = specs.Root{
|
|
Path: filepath.Dir(c.BaseFS),
|
|
Readonly: c.HostConfig.ReadonlyRootfs,
|
|
}
|
|
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
|
if err := c.SetupWorkingDirectory(rootUID, rootGID); err != nil {
|
|
return err
|
|
}
|
|
cwd := c.Config.WorkingDir
|
|
s.Process.Args = append([]string{c.Path}, c.Args...)
|
|
s.Process.Cwd = cwd
|
|
s.Process.Env = c.CreateDaemonEnvironment(c.Config.Tty, linkedEnv)
|
|
s.Process.Terminal = c.Config.Tty
|
|
s.Hostname = c.FullHostname()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
|
|
s := oci.DefaultSpec()
|
|
if err := daemon.populateCommonSpec(&s, c); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := setResources(&s, c.HostConfig.Resources); err != nil {
|
|
return nil, fmt.Errorf("runtime spec resources: %v", err)
|
|
}
|
|
|
|
if err := setUser(&s, c); err != nil {
|
|
return nil, fmt.Errorf("spec user: %v", err)
|
|
}
|
|
|
|
if err := daemon.setNetworkInterface(&s, c); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := daemon.setupIpcDirs(c); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ms, err := daemon.setupMounts(c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ms = append(ms, c.IpcMounts()...)
|
|
tmpfsMounts, err := c.TmpfsMounts()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ms = append(ms, tmpfsMounts...)
|
|
sort.Sort(mounts(ms))
|
|
|
|
return (*specs.Spec)(&s), nil
|
|
}
|
|
|
|
// mergeUlimits merge the Ulimits from HostConfig with daemon defaults, and update HostConfig
|
|
// It will do nothing on non-Linux platform
|
|
func (daemon *Daemon) mergeUlimits(c *containertypes.HostConfig) {
|
|
return
|
|
}
|