Skip to content

Commit

Permalink
Delegate data directory configuration in the sandbox to the controller.
Browse files Browse the repository at this point in the history
Because this library should not assume that /var/lib/docker is
always the root path.

Signed-off-by: David Calavera <david.calavera@gmail.com>
  • Loading branch information
calavera committed Jan 19, 2016
1 parent 8a86487 commit 59b5217
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 35 deletions.
20 changes: 16 additions & 4 deletions controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,10 @@ type controller struct {
sync.Mutex
}

// New creates a new instance of network controller.
func New(cfgOptions ...config.Option) (NetworkController, error) {
var cfg *config.Config
cfg = &config.Config{
// newControllerConfig creates a new configuration based in
// the options supplied. It also loads the default scopes for it.
func newControllerConfig(cfgOptions ...config.Option) *config.Config {
cfg := &config.Config{
Daemon: config.DaemonCfg{
DriverCfg: make(map[string]interface{}),
},
Expand All @@ -164,6 +164,12 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
cfg.ProcessOptions(cfgOptions...)
}
cfg.LoadDefaultScopes(cfg.Daemon.DataDir)
return cfg
}

// New creates a new instance of network controller.
func New(cfgOptions ...config.Option) (NetworkController, error) {
cfg := newControllerConfig(cfgOptions...)

c := &controller{
id: stringid.GenerateRandomID(),
Expand Down Expand Up @@ -730,3 +736,9 @@ func (c *controller) Stop() {
c.stopExternalKeyListener()
osl.GC()
}

// DataDir returns the path to where
// the network controller stores container data.
func (c *controller) DataDir() string {
return c.cfg.Daemon.DataDir
}
71 changes: 43 additions & 28 deletions sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ func (sb *sandbox) delete(force bool) error {
}
// Container is going away. Path cache in etchosts is most
// likely not required any more. Drop it.
etchosts.Drop(sb.config.hostsPath)
etchosts.Drop(sb.hostsPath())

if sb.resolver != nil {
sb.resolver.Stop()
Expand Down Expand Up @@ -714,25 +714,42 @@ func (sb *sandbox) clearNetworkResources(origEp *endpoint) error {
}

const (
defaultPrefix = "/var/lib/docker/network/files"
dirPerm = 0755
filePerm = 0644
dirPerm = 0755
filePerm = 0644
)

func (sb *sandbox) buildHostsFile() error {
// hostsPath returns the path location for the sandbox hosts file.
// It initializes the path based on the controller data directory
// if the config path is empty.
func (sb *sandbox) hostsPath() string {
if sb.config.hostsPath == "" {
sb.config.hostsPath = defaultPrefix + "/" + sb.id + "/hosts"
sb.config.hostsPath = filepath.Join(sb.controller.DataDir(), sb.id, "hosts")
}
return sb.config.hostsPath
}

// resolvConfPath returns the path location for the sandbox resolvConf file.
// It initializes the path based on the controller data directory
// if the config path is empty.
func (sb *sandbox) resolvConfPath() string {
if sb.config.resolvConfPath == "" {
sb.config.resolvConfPath = filepath.Join(sb.controller.DataDir(), sb.id, "resolv.conf")
}
return sb.config.resolvConfPath
}

func (sb *sandbox) buildHostsFile() error {
hostsPath := sb.hostsPath()

dir, _ := filepath.Split(sb.config.hostsPath)
dir, _ := filepath.Split(hostsPath)
if err := createBasePath(dir); err != nil {
return err
}

// This is for the host mode networking
if sb.config.originHostsPath != "" {
if err := copyFile(sb.config.originHostsPath, sb.config.hostsPath); err != nil && !os.IsNotExist(err) {
return types.InternalErrorf("could not copy source hosts file %s to %s: %v", sb.config.originHostsPath, sb.config.hostsPath, err)
if err := copyFile(sb.config.originHostsPath, hostsPath); err != nil && !os.IsNotExist(err) {
return types.InternalErrorf("could not copy source hosts file %s to %s: %v", sb.config.originHostsPath, hostsPath, err)
}
return nil
}
Expand All @@ -742,7 +759,7 @@ func (sb *sandbox) buildHostsFile() error {
extraContent = append(extraContent, etchosts.Record{Hosts: extraHost.name, IP: extraHost.IP})
}

return etchosts.Build(sb.config.hostsPath, "", sb.config.hostName, sb.config.domainName, extraContent)
return etchosts.Build(hostsPath, "", sb.config.hostName, sb.config.domainName, extraContent)
}

func (sb *sandbox) updateHostsFile(ifaceIP string) error {
Expand All @@ -766,13 +783,13 @@ func (sb *sandbox) updateHostsFile(ifaceIP string) error {
}

func (sb *sandbox) addHostsEntries(recs []etchosts.Record) {
if err := etchosts.Add(sb.config.hostsPath, recs); err != nil {
if err := etchosts.Add(sb.hostsPath(), recs); err != nil {
log.Warnf("Failed adding service host entries to the running container: %v", err)
}
}

func (sb *sandbox) deleteHostsEntries(recs []etchosts.Record) {
if err := etchosts.Delete(sb.config.hostsPath, recs); err != nil {
if err := etchosts.Delete(sb.hostsPath(), recs); err != nil {
log.Warnf("Failed deleting service host entries to the running container: %v", err)
}
}
Expand All @@ -785,7 +802,7 @@ func (sb *sandbox) updateParentHosts() error {
if pSb == nil {
continue
}
if err := etchosts.Update(pSb.(*sandbox).config.hostsPath, update.ip, update.name); err != nil {
if err := etchosts.Update(pSb.(*sandbox).hostsPath(), update.ip, update.name); err != nil {
return err
}
}
Expand All @@ -795,22 +812,19 @@ func (sb *sandbox) updateParentHosts() error {

func (sb *sandbox) setupDNS() error {
var newRC *resolvconf.File
resolvConfPath := sb.resolvConfPath()

if sb.config.resolvConfPath == "" {
sb.config.resolvConfPath = defaultPrefix + "/" + sb.id + "/resolv.conf"
}

sb.config.resolvConfHashFile = sb.config.resolvConfPath + ".hash"
sb.config.resolvConfHashFile = resolvConfPath + ".hash"

dir, _ := filepath.Split(sb.config.resolvConfPath)
dir, _ := filepath.Split(resolvConfPath)
if err := createBasePath(dir); err != nil {
return err
}

// This is for the host mode networking
if sb.config.originResolvConfPath != "" {
if err := copyFile(sb.config.originResolvConfPath, sb.config.resolvConfPath); err != nil {
return fmt.Errorf("could not copy source resolv.conf file %s to %s: %v", sb.config.originResolvConfPath, sb.config.resolvConfPath, err)
if err := copyFile(sb.config.originResolvConfPath, resolvConfPath); err != nil {
return fmt.Errorf("could not copy source resolv.conf file %s to %s: %v", sb.config.originResolvConfPath, resolvConfPath, err)
}
return nil
}
Expand All @@ -836,7 +850,7 @@ func (sb *sandbox) setupDNS() error {
if len(sb.config.dnsOptionsList) > 0 {
dnsOptionsList = sb.config.dnsOptionsList
}
newRC, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList)
newRC, err = resolvconf.Build(resolvConfPath, dnsList, dnsSearchList, dnsOptionsList)
if err != nil {
return err
}
Expand All @@ -846,7 +860,7 @@ func (sb *sandbox) setupDNS() error {
return err
}
// No contention on container resolv.conf file at sandbox creation
if err := ioutil.WriteFile(sb.config.resolvConfPath, newRC.Content, filePerm); err != nil {
if err := ioutil.WriteFile(resolvConfPath, newRC.Content, filePerm); err != nil {
return types.InternalErrorf("failed to write unhaltered resolv.conf file content when setting up dns for sandbox %s: %v", sb.ID(), err)
}
}
Expand All @@ -861,15 +875,16 @@ func (sb *sandbox) setupDNS() error {

func (sb *sandbox) updateDNS(ipv6Enabled bool) error {
var (
currHash string
hashFile = sb.config.resolvConfHashFile
currHash string
hashFile = sb.config.resolvConfHashFile
resolvConfPath = sb.resolvConfPath()
)

if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 {
return nil
}

currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath)
currRC, err := resolvconf.GetSpecific(resolvConfPath)
if err != nil {
if !os.IsNotExist(err) {
return err
Expand Down Expand Up @@ -899,7 +914,7 @@ func (sb *sandbox) updateDNS(ipv6Enabled bool) error {
}

// for atomic updates to these files, use temporary files with os.Rename:
dir := path.Dir(sb.config.resolvConfPath)
dir := path.Dir(resolvConfPath)
tmpHashFile, err := ioutil.TempFile(dir, "hash")
if err != nil {
return err
Expand All @@ -926,7 +941,7 @@ func (sb *sandbox) updateDNS(ipv6Enabled bool) error {
if err = os.Rename(tmpHashFile.Name(), hashFile); err != nil {
return err
}
return os.Rename(tmpResolvFile.Name(), sb.config.resolvConfPath)
return os.Rename(tmpResolvFile.Name(), resolvConfPath)
}

// Embedded DNS server has to be enabled for this sandbox. Rebuild the container's
Expand Down
50 changes: 47 additions & 3 deletions sandbox_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package libnetwork

import (
"io/ioutil"
"os"
"strings"
"testing"

"github.com/docker/libnetwork/config"
Expand All @@ -10,8 +13,15 @@ import (
"github.com/docker/libnetwork/testutils"
)

func createEmptyCtrlr() *controller {
return &controller{sandboxes: sandboxTable{}}
func createEmptyCtrlr(t *testing.T) (*controller, func()) {
ctrlr := &controller{sandboxes: sandboxTable{}}

tmp, err := ioutil.TempDir("", "libnetwork-")
if err != nil {
t.Fatal(err)
}
ctrlr.cfg = newControllerConfig(config.OptionDataDir(tmp))
return ctrlr, func() { os.RemoveAll(tmp) }
}

func getTestEnv(t *testing.T) (NetworkController, Network, Network) {
Expand Down Expand Up @@ -58,7 +68,8 @@ func getTestEnv(t *testing.T) (NetworkController, Network, Network) {
}

func TestSandboxAddEmpty(t *testing.T) {
ctrlr := createEmptyCtrlr()
ctrlr, cleanup := createEmptyCtrlr(t)
defer cleanup()

sbx, err := ctrlr.NewSandbox("sandbox0")
if err != nil {
Expand Down Expand Up @@ -211,3 +222,36 @@ func TestSandboxAddSamePrio(t *testing.T) {

osl.GC()
}

func TestSandboxDataDir(t *testing.T) {
ctrlr, cleanup := createEmptyCtrlr(t)
defer cleanup()

sbx, err := ctrlr.NewSandbox("sandbox0")
if err != nil {
t.Fatal(err)
}

s, ok := sbx.(*sandbox)
if !ok {
t.Fatal("Sandbox is not a sandbox struct")
}

h := s.hostsPath()
if !strings.HasPrefix(h, ctrlr.DataDir()) {
t.Fatalf("Expected %s to be the hosts parent directory, got %s", ctrlr.DataDir(), h)
}

r := s.resolvConfPath()
if !strings.HasPrefix(r, ctrlr.DataDir()) {
t.Fatalf("Expected %s to be the resolv conf parent directory, got %s", ctrlr.DataDir(), r)
}

defer func() {
if err := sbx.Delete(); err != nil {
t.Fatal(err)
}

osl.GC()
}()
}

0 comments on commit 59b5217

Please sign in to comment.