| 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 |
| } |