1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Docker changes for libnetwork Sandbox

- Ground-work for integrating with user namespace support

Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
Alessandro Boch 2015-09-02 16:43:28 -07:00
parent 414dfbf681
commit 56fdb05258
5 changed files with 85 additions and 74 deletions

View file

@ -392,32 +392,34 @@ func (container *Container) buildHostnameFile() error {
return ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644) return ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
} }
func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, error) { func (container *Container) buildSandboxOptions() ([]libnetwork.SandboxOption, error) {
var ( var (
joinOptions []libnetwork.EndpointOption sboxOptions []libnetwork.SandboxOption
err error err error
dns []string dns []string
dnsSearch []string dnsSearch []string
) )
joinOptions = append(joinOptions, libnetwork.JoinOptionHostname(container.Config.Hostname), sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname),
libnetwork.JoinOptionDomainname(container.Config.Domainname)) libnetwork.OptionDomainname(container.Config.Domainname))
if container.hostConfig.NetworkMode.IsHost() { if container.hostConfig.NetworkMode.IsHost() {
joinOptions = append(joinOptions, libnetwork.JoinOptionUseDefaultSandbox()) sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox())
sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf"))
} }
container.HostsPath, err = container.getRootResourcePath("hosts") container.HostsPath, err = container.getRootResourcePath("hosts")
if err != nil { if err != nil {
return nil, err return nil, err
} }
joinOptions = append(joinOptions, libnetwork.JoinOptionHostsPath(container.HostsPath)) sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath))
container.ResolvConfPath, err = container.getRootResourcePath("resolv.conf") container.ResolvConfPath, err = container.getRootResourcePath("resolv.conf")
if err != nil { if err != nil {
return nil, err return nil, err
} }
joinOptions = append(joinOptions, libnetwork.JoinOptionResolvConfPath(container.ResolvConfPath)) sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath))
if len(container.hostConfig.DNS) > 0 { if len(container.hostConfig.DNS) > 0 {
dns = container.hostConfig.DNS dns = container.hostConfig.DNS
@ -426,7 +428,7 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err
} }
for _, d := range dns { for _, d := range dns {
joinOptions = append(joinOptions, libnetwork.JoinOptionDNS(d)) sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d))
} }
if len(container.hostConfig.DNSSearch) > 0 { if len(container.hostConfig.DNSSearch) > 0 {
@ -436,7 +438,7 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err
} }
for _, ds := range dnsSearch { for _, ds := range dnsSearch {
joinOptions = append(joinOptions, libnetwork.JoinOptionDNSSearch(ds)) sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds))
} }
if container.NetworkSettings.SecondaryIPAddresses != nil { if container.NetworkSettings.SecondaryIPAddresses != nil {
@ -446,7 +448,7 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err
} }
for _, a := range container.NetworkSettings.SecondaryIPAddresses { for _, a := range container.NetworkSettings.SecondaryIPAddresses {
joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(name, a.Addr)) sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr))
} }
} }
@ -465,7 +467,7 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err
if alias != child.Name[1:] { if alias != child.Name[1:] {
aliasList = aliasList + " " + child.Name[1:] aliasList = aliasList + " " + child.Name[1:]
} }
joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(aliasList, child.NetworkSettings.IPAddress)) sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.IPAddress))
if child.NetworkSettings.EndpointID != "" { if child.NetworkSettings.EndpointID != "" {
childEndpoints = append(childEndpoints, child.NetworkSettings.EndpointID) childEndpoints = append(childEndpoints, child.NetworkSettings.EndpointID)
} }
@ -474,7 +476,7 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err
for _, extraHost := range container.hostConfig.ExtraHosts { for _, extraHost := range container.hostConfig.ExtraHosts {
// allow IPv6 addresses in extra hosts; only split on first ":" // allow IPv6 addresses in extra hosts; only split on first ":"
parts := strings.SplitN(extraHost, ":", 2) parts := strings.SplitN(extraHost, ":", 2)
joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(parts[0], parts[1])) sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1]))
} }
refs := container.daemon.containerGraph().RefPaths(container.ID) refs := container.daemon.containerGraph().RefPaths(container.ID)
@ -490,7 +492,7 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err
if c != nil && !container.daemon.configStore.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() { if c != nil && !container.daemon.configStore.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() {
logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, container.NetworkSettings.IPAddress) logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, container.NetworkSettings.IPAddress)
joinOptions = append(joinOptions, libnetwork.JoinOptionParentUpdate(c.NetworkSettings.EndpointID, ref.Name, container.NetworkSettings.IPAddress)) sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(c.ID, ref.Name, container.NetworkSettings.IPAddress))
if c.NetworkSettings.EndpointID != "" { if c.NetworkSettings.EndpointID != "" {
parentEndpoints = append(parentEndpoints, c.NetworkSettings.EndpointID) parentEndpoints = append(parentEndpoints, c.NetworkSettings.EndpointID)
} }
@ -504,9 +506,9 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err
}, },
} }
joinOptions = append(joinOptions, libnetwork.JoinOptionGeneric(linkOptions)) sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions))
return joinOptions, nil return sboxOptions, nil
} }
func (container *Container) buildPortMapInfo(n libnetwork.Network, ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) { func (container *Container) buildPortMapInfo(n libnetwork.Network, ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) {
@ -630,12 +632,10 @@ func (container *Container) updateJoinInfo(ep libnetwork.Endpoint) error {
container.NetworkSettings.IPv6Gateway = epInfo.GatewayIPv6().String() container.NetworkSettings.IPv6Gateway = epInfo.GatewayIPv6().String()
} }
container.NetworkSettings.SandboxKey = epInfo.SandboxKey()
return nil return nil
} }
func (container *Container) updateNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error { func (container *Container) updateEndpointNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error {
networkSettings := &network.Settings{NetworkID: n.ID(), EndpointID: ep.ID()} networkSettings := &network.Settings{NetworkID: n.ID(), EndpointID: ep.ID()}
networkSettings, err := container.buildPortMapInfo(n, ep, networkSettings) networkSettings, err := container.buildPortMapInfo(n, ep, networkSettings)
@ -656,35 +656,30 @@ func (container *Container) updateNetworkSettings(n libnetwork.Network, ep libne
return nil return nil
} }
func (container *Container) updateSandboxNetworkSettings(sb libnetwork.Sandbox) error {
container.NetworkSettings.SandboxID = sb.ID()
container.NetworkSettings.SandboxKey = sb.Key()
return nil
}
// UpdateNetwork is used to update the container's network (e.g. when linked containers // UpdateNetwork is used to update the container's network (e.g. when linked containers
// get removed/unlinked). // get removed/unlinked).
func (container *Container) updateNetwork() error { func (container *Container) updateNetwork() error {
n, err := container.daemon.netController.NetworkByID(container.NetworkSettings.NetworkID) ctrl := container.daemon.netController
sid := container.NetworkSettings.SandboxID
sb, err := ctrl.SandboxByID(sid)
if err != nil { if err != nil {
return fmt.Errorf("error locating network id %s: %v", container.NetworkSettings.NetworkID, err) return fmt.Errorf("error locating sandbox id %s: %v", sid, err)
} }
ep, err := n.EndpointByID(container.NetworkSettings.EndpointID) options, err := container.buildSandboxOptions()
if err != nil {
return fmt.Errorf("error locating endpoint id %s: %v", container.NetworkSettings.EndpointID, err)
}
if err := ep.Leave(container.ID); err != nil {
return fmt.Errorf("endpoint leave failed: %v", err)
}
joinOptions, err := container.buildJoinOptions()
if err != nil { if err != nil {
return fmt.Errorf("Update network failed: %v", err) return fmt.Errorf("Update network failed: %v", err)
} }
if err := ep.Join(container.ID, joinOptions...); err != nil { if err := sb.Refresh(options...); err != nil {
return fmt.Errorf("endpoint join failed: %v", err) return fmt.Errorf("Update network failed: Failure in refresh sandbox %s: %v", sid, err)
}
if err := container.updateJoinInfo(ep); err != nil {
return fmt.Errorf("Updating join info failed: %v", err)
} }
return nil return nil
@ -871,6 +866,7 @@ func (container *Container) allocateNetwork() error {
func (container *Container) configureNetwork(networkName, service, networkDriver string, canCreateNetwork bool) error { func (container *Container) configureNetwork(networkName, service, networkDriver string, canCreateNetwork bool) error {
controller := container.daemon.netController controller := container.daemon.netController
n, err := controller.NetworkByName(networkName) n, err := controller.NetworkByName(networkName)
if err != nil { if err != nil {
if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok || !canCreateNetwork { if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok || !canCreateNetwork {
@ -899,16 +895,32 @@ func (container *Container) configureNetwork(networkName, service, networkDriver
} }
} }
if err := container.updateNetworkSettings(n, ep); err != nil { if err := container.updateEndpointNetworkSettings(n, ep); err != nil {
return err return err
} }
joinOptions, err := container.buildJoinOptions() var sb libnetwork.Sandbox
if err != nil { controller.WalkSandboxes(func(s libnetwork.Sandbox) bool {
return err if s.ContainerID() == container.ID {
sb = s
return true
}
return false
})
if sb == nil {
options, err := container.buildSandboxOptions()
if err != nil {
return err
}
sb, err = controller.NewSandbox(container.ID, options...)
if err != nil {
return err
}
} }
if err := ep.Join(container.ID, joinOptions...); err != nil { container.updateSandboxNetworkSettings(sb)
if err := ep.Join(sb); err != nil {
return err return err
} }
@ -1038,12 +1050,19 @@ func (container *Container) releaseNetwork() {
return return
} }
sid := container.NetworkSettings.SandboxID
eid := container.NetworkSettings.EndpointID eid := container.NetworkSettings.EndpointID
nid := container.NetworkSettings.NetworkID nid := container.NetworkSettings.NetworkID
container.NetworkSettings = &network.Settings{} container.NetworkSettings = &network.Settings{}
if nid == "" || eid == "" { if sid == "" || nid == "" || eid == "" {
return
}
sb, err := container.daemon.netController.SandboxByID(sid)
if err != nil {
logrus.Errorf("error locating sandbox id %s: %v", sid, err)
return return
} }
@ -1059,17 +1078,9 @@ func (container *Container) releaseNetwork() {
return return
} }
switch { if err := sb.Delete(); err != nil {
case container.hostConfig.NetworkMode.IsHost(): logrus.Errorf("Error deleting sandbox id %s for container %s: %v", sid, container.ID, err)
if err := ep.Leave(container.ID); err != nil { return
logrus.Errorf("Error leaving endpoint id %s for container %s: %v", eid, container.ID, err)
return
}
default:
if err := container.daemon.netController.LeaveAll(container.ID); err != nil {
logrus.Errorf("Leave all failed for %s: %v", container.ID, err)
return
}
} }
// In addition to leaving all endpoints, delete implicitly created endpoint // In addition to leaving all endpoints, delete implicitly created endpoint

View file

@ -13,6 +13,7 @@ type Address struct {
type Settings struct { type Settings struct {
Bridge string Bridge string
EndpointID string EndpointID string
SandboxID string
Gateway string Gateway string
GlobalIPv6Address string GlobalIPv6Address string
GlobalIPv6PrefixLen int GlobalIPv6PrefixLen int

View file

@ -6,7 +6,7 @@ import (
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/daemon/execdriver"
"github.com/docker/libnetwork/sandbox" "github.com/docker/libnetwork/osl"
"github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer"
) )
@ -86,16 +86,12 @@ func (daemon *Daemon) getNetworkStats(name string) ([]*libcontainer.NetworkInter
return list, err return list, err
} }
nw, err := daemon.netController.NetworkByID(c.NetworkSettings.NetworkID) sb, err := daemon.netController.SandboxByID(c.NetworkSettings.SandboxID)
if err != nil {
return list, err
}
ep, err := nw.EndpointByID(c.NetworkSettings.EndpointID)
if err != nil { if err != nil {
return list, err return list, err
} }
stats, err := ep.Statistics() stats, err := sb.Statistics()
if err != nil { if err != nil {
return list, err return list, err
} }
@ -108,7 +104,7 @@ func (daemon *Daemon) getNetworkStats(name string) ([]*libcontainer.NetworkInter
return list, nil return list, nil
} }
func convertLnNetworkStats(name string, stats *sandbox.InterfaceStatistics) *libcontainer.NetworkInterface { func convertLnNetworkStats(name string, stats *osl.InterfaceStatistics) *libcontainer.NetworkInterface {
n := &libcontainer.NetworkInterface{Name: name} n := &libcontainer.NetworkInterface{Name: name}
n.RxBytes = stats.RxBytes n.RxBytes = stats.RxBytes
n.RxPackets = stats.RxPackets n.RxPackets = stats.RxPackets

View file

@ -1524,19 +1524,23 @@ func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) {
if err != nil { if err != nil {
c.Fatal(out, err) c.Fatal(out, err)
} }
// Get sandbox key via inspect
out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.SandboxKey}}'", "netns")
if err != nil {
c.Fatalf("Error inspecting container: %s, %v", out, err)
}
fileName := strings.Trim(out, " \r\n'")
if out, err := s.d.Cmd("stop", "netns"); err != nil { if out, err := s.d.Cmd("stop", "netns"); err != nil {
c.Fatal(out, err) c.Fatal(out, err)
} }
// Construct netns file name from container id
out = strings.TrimSpace(out)
nsFile := out[:12]
// Test if the file still exists // Test if the file still exists
out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", "/var/run/docker/netns/"+nsFile)) out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName))
out = strings.TrimSpace(out) out = strings.TrimSpace(out)
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
c.Assert(out, check.Equals, "/var/run/docker/netns/"+nsFile, check.Commentf("Output: %s", out)) c.Assert(out, check.Equals, fileName, check.Commentf("Output: %s", out))
// Remove the container and restart the daemon // Remove the container and restart the daemon
if out, err := s.d.Cmd("rm", "netns"); err != nil { if out, err := s.d.Cmd("rm", "netns"); err != nil {
@ -1548,10 +1552,9 @@ func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) {
} }
// Test again and see now the netns file does not exist // Test again and see now the netns file does not exist
out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", "/var/run/docker/netns/"+nsFile)) out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName))
out = strings.TrimSpace(out) out = strings.TrimSpace(out)
c.Assert(err, check.Not(check.IsNil), check.Commentf("Output: %s", out)) c.Assert(err, check.Not(check.IsNil), check.Commentf("Output: %s", out))
// c.Assert(out, check.Equals, "", check.Commentf("Output: %s", out))
} }
// tests regression detailed in #13964 where DOCKER_TLS_VERIFY env is ignored // tests regression detailed in #13964 where DOCKER_TLS_VERIFY env is ignored

View file

@ -865,7 +865,7 @@ func (s *DockerSuite) TestRunDnsDefaultOptions(c *check.C) {
// check that the actual defaults are appended to the commented out // check that the actual defaults are appended to the commented out
// localhost resolver (which should be preserved) // localhost resolver (which should be preserved)
// NOTE: if we ever change the defaults from google dns, this will break // NOTE: if we ever change the defaults from google dns, this will break
expected := "#nameserver 127.0.2.1\n\nnameserver 8.8.8.8\nnameserver 8.8.4.4" expected := "#nameserver 127.0.2.1\n\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n"
if actual != expected { if actual != expected {
c.Fatalf("expected resolv.conf be: %q, but was: %q", expected, actual) c.Fatalf("expected resolv.conf be: %q, but was: %q", expected, actual)
} }
@ -880,7 +880,7 @@ func (s *DockerSuite) TestRunDnsOptions(c *check.C) {
} }
actual := strings.Replace(strings.Trim(out, "\r\n"), "\n", " ", -1) actual := strings.Replace(strings.Trim(out, "\r\n"), "\n", " ", -1)
if actual != "nameserver 127.0.0.1 search mydomain" { if actual != "search mydomain nameserver 127.0.0.1" {
c.Fatalf("expected 'nameserver 127.0.0.1 search mydomain', but says: %q", actual) c.Fatalf("expected 'nameserver 127.0.0.1 search mydomain', but says: %q", actual)
} }
@ -1001,7 +1001,7 @@ func (s *DockerSuite) TestRunNonRootUserResolvName(c *check.C) {
func (s *DockerSuite) TestRunResolvconfUpdate(c *check.C) { func (s *DockerSuite) TestRunResolvconfUpdate(c *check.C) {
testRequires(c, SameHostDaemon) testRequires(c, SameHostDaemon)
tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78") tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\n")
tmpLocalhostResolvConf := []byte("nameserver 127.0.0.1") tmpLocalhostResolvConf := []byte("nameserver 127.0.0.1")
//take a copy of resolv.conf for restoring after test completes //take a copy of resolv.conf for restoring after test completes
@ -1131,7 +1131,7 @@ func (s *DockerSuite) TestRunResolvconfUpdate(c *check.C) {
c.Fatal(err) c.Fatal(err)
} }
expected := "\nnameserver 8.8.8.8\nnameserver 8.8.4.4" expected := "\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n"
if !bytes.Equal(containerResolv, []byte(expected)) { if !bytes.Equal(containerResolv, []byte(expected)) {
c.Fatalf("Container does not have cleaned/replaced DNS in resolv.conf; expected %q, got %q", expected, string(containerResolv)) c.Fatalf("Container does not have cleaned/replaced DNS in resolv.conf; expected %q, got %q", expected, string(containerResolv))
} }