diff --git a/initialize/config.go b/initialize/config.go index 3ef6da9..3e9c64e 100644 --- a/initialize/config.go +++ b/initialize/config.go @@ -170,16 +170,13 @@ func Apply(cfg config.CloudConfig, env *Environment) error { case "digitalocean": interfaces, err = network.ProcessDigitalOceanNetconf(cfg.NetworkConfig) default: - return fmt.Errorf("Unsupported network config format %q", env.NetconfType()) + err = fmt.Errorf("Unsupported network config format %q", env.NetconfType()) } - if err != nil { return err } - if err := system.WriteNetworkdConfigs(interfaces); err != nil { - return err - } + units = append(units, createNetworkingUnits(interfaces)...) if err := system.RestartNetwork(interfaces); err != nil { return err } @@ -187,7 +184,25 @@ func Apply(cfg config.CloudConfig, env *Environment) error { um := system.NewUnitManager(env.Root()) return processUnits(units, env.Root(), um) +} +func createNetworkingUnits(interfaces []network.InterfaceGenerator) (units []system.Unit) { + appendNewUnit := func(units []system.Unit, name, content string) []system.Unit { + if content == "" { + return units + } + return append(units, system.Unit{Unit: config.Unit{ + Name: name, + Runtime: true, + Content: content, + }}) + } + for _, i := range interfaces { + units = appendNewUnit(units, fmt.Sprintf("%s.netdev", i.Filename()), i.Netdev()) + units = appendNewUnit(units, fmt.Sprintf("%s.link", i.Filename()), i.Link()) + units = appendNewUnit(units, fmt.Sprintf("%s.network", i.Filename()), i.Network()) + } + return units } // processUnits takes a set of Units and applies them to the given root using diff --git a/initialize/config_test.go b/initialize/config_test.go index 0dad5a4..8f7dda5 100644 --- a/initialize/config_test.go +++ b/initialize/config_test.go @@ -21,6 +21,7 @@ import ( "testing" "github.com/coreos/coreos-cloudinit/config" + "github.com/coreos/coreos-cloudinit/network" "github.com/coreos/coreos-cloudinit/system" ) @@ -67,6 +68,86 @@ func (tum *TestUnitManager) UnmaskUnit(u system.Unit) error { return nil } +type mockInterface struct { + name string + filename string + netdev string + link string + network string + kind string + modprobeParams string +} + +func (i mockInterface) Name() string { + return i.name +} + +func (i mockInterface) Filename() string { + return i.filename +} + +func (i mockInterface) Netdev() string { + return i.netdev +} + +func (i mockInterface) Link() string { + return i.link +} + +func (i mockInterface) Network() string { + return i.network +} + +func (i mockInterface) Type() string { + return i.kind +} + +func (i mockInterface) ModprobeParams() string { + return i.modprobeParams +} + +func TestCreateNetworkingUnits(t *testing.T) { + for _, tt := range []struct { + interfaces []network.InterfaceGenerator + expect []system.Unit + }{ + {nil, nil}, + { + []network.InterfaceGenerator{ + network.InterfaceGenerator(mockInterface{filename: "test"}), + }, + nil, + }, + { + []network.InterfaceGenerator{ + network.InterfaceGenerator(mockInterface{filename: "test1", netdev: "test netdev"}), + network.InterfaceGenerator(mockInterface{filename: "test2", link: "test link"}), + network.InterfaceGenerator(mockInterface{filename: "test3", network: "test network"}), + }, + []system.Unit{ + system.Unit{Unit: config.Unit{Name: "test1.netdev", Runtime: true, Content: "test netdev"}}, + system.Unit{Unit: config.Unit{Name: "test2.link", Runtime: true, Content: "test link"}}, + system.Unit{Unit: config.Unit{Name: "test3.network", Runtime: true, Content: "test network"}}, + }, + }, + { + []network.InterfaceGenerator{ + network.InterfaceGenerator(mockInterface{filename: "test", netdev: "test netdev", link: "test link", network: "test network"}), + }, + []system.Unit{ + system.Unit{Unit: config.Unit{Name: "test.netdev", Runtime: true, Content: "test netdev"}}, + system.Unit{Unit: config.Unit{Name: "test.link", Runtime: true, Content: "test link"}}, + system.Unit{Unit: config.Unit{Name: "test.network", Runtime: true, Content: "test network"}}, + }, + }, + } { + units := createNetworkingUnits(tt.interfaces) + if !reflect.DeepEqual(tt.expect, units) { + t.Errorf("bad units (%+v): want %#v, got %#v", tt.interfaces, tt.expect, units) + } + } +} + func TestProcessUnits(t *testing.T) { tests := []struct { units []system.Unit diff --git a/system/networkd.go b/system/networkd.go index 056eb6a..dac2d81 100644 --- a/system/networkd.go +++ b/system/networkd.go @@ -29,10 +29,6 @@ import ( "github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/dotcloud/docker/pkg/netlink" ) -const ( - runtimeNetworkPath = "/run/systemd/network" -) - func RestartNetwork(interfaces []network.InterfaceGenerator) (err error) { defer func() { if e := restartNetworkd(); e != nil { @@ -100,30 +96,3 @@ func restartNetworkd() error { _, err := NewUnitManager("").RunUnitCommand(networkd, "restart") return err } - -func WriteNetworkdConfigs(interfaces []network.InterfaceGenerator) error { - for _, iface := range interfaces { - filename := fmt.Sprintf("%s.netdev", iface.Filename()) - if err := writeConfig(filename, iface.Netdev()); err != nil { - return err - } - filename = fmt.Sprintf("%s.link", iface.Filename()) - if err := writeConfig(filename, iface.Link()); err != nil { - return err - } - filename = fmt.Sprintf("%s.network", iface.Filename()) - if err := writeConfig(filename, iface.Network()); err != nil { - return err - } - } - return nil -} - -func writeConfig(filename string, content string) error { - if content == "" { - return nil - } - log.Printf("Writing networkd unit %q\n", filename) - _, err := WriteFile(&File{config.File{Content: content, Path: filename}}, runtimeNetworkPath) - return err -}