From 59a752c306b4518068ea8a833654ef3c40a90b15 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Tue, 21 Mar 2017 10:26:52 +0000 Subject: [PATCH] Use the partial cfg for the initial network and release the network device from dhcp if we're not using it Signed-off-by: Sven Dowideit --- cmd/cloudinitsave/cloudinitsave.go | 22 +-- cmd/control/install.go | 2 +- cmd/network/network.go | 2 +- init/init.go | 7 + netconf/netconf_linux.go | 22 +-- tests/assets/multi_nic/cloud-config.yml | 4 +- tests/network_from_url_test.go | 2 +- tests/network_test.go | 219 +++++++++++++++++++----- 8 files changed, 207 insertions(+), 73 deletions(-) diff --git a/cmd/cloudinitsave/cloudinitsave.go b/cmd/cloudinitsave/cloudinitsave.go index 80cc5eba..ad5fd050 100755 --- a/cmd/cloudinitsave/cloudinitsave.go +++ b/cmd/cloudinitsave/cloudinitsave.go @@ -26,7 +26,6 @@ import ( yaml "github.com/cloudfoundry-incubator/candiedyaml" - "github.com/rancher/os/cmd/control" "github.com/rancher/os/cmd/network" rancherConfig "github.com/rancher/os/config" "github.com/rancher/os/config/cloudinit/config" @@ -55,26 +54,17 @@ func Main() { log.InitLogger() log.Info("Running cloud-init-save") - if err := control.UdevSettle(); err != nil { - log.Errorf("Failed to run udev settle: %v", err) - } - - cfg := rancherConfig.LoadConfig() - network.ApplyNetworkConfig(cfg) - if err := SaveCloudConfig(); err != nil { log.Errorf("Failed to save cloud-config: %v", err) } - - // Apply any newly detected network config. - //consider putting this in a separate init phase... - cfg = rancherConfig.LoadConfig() - network.ApplyNetworkConfig(cfg) } func SaveCloudConfig() error { log.Debugf("SaveCloudConfig") + cfg := rancherConfig.LoadConfig() + log.Debugf("init: SaveCloudConfig(pre ApplyNetworkConfig): %#v", cfg.Rancher.Network) + network.ApplyNetworkConfig(cfg) dss := getDatasources(cfg) if len(dss) == 0 { @@ -83,6 +73,12 @@ func SaveCloudConfig() error { } selectDatasource(dss) + + // Apply any newly detected network config. + cfg = rancherConfig.LoadConfig() + log.Debugf("init: SaveCloudConfig(post ApplyNetworkConfig): %#v", cfg.Rancher.Network) + network.ApplyNetworkConfig(cfg) + return nil } diff --git a/cmd/control/install.go b/cmd/control/install.go index 6c085c48..b5ee09be 100755 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -354,7 +354,7 @@ func mountBootIso() error { os.MkdirAll("/bootiso", 0755) cmd := exec.Command("mount", "-t", deviceType, deviceName, "/bootiso") - log.Infof("mount (%#v)", cmd) + log.Debugf("mount (%#v)", cmd) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr err = cmd.Run() diff --git a/cmd/network/network.go b/cmd/network/network.go index dce8a734..ded2f357 100755 --- a/cmd/network/network.go +++ b/cmd/network/network.go @@ -11,7 +11,6 @@ import ( func Main() { log.InitLogger() - log.Infof("Running network") cfg := config.LoadConfig() ApplyNetworkConfig(cfg) @@ -20,6 +19,7 @@ func Main() { } func ApplyNetworkConfig(cfg *config.CloudConfig) { + log.Infof("Apply Network Config") nameservers := cfg.Rancher.Network.DNS.Nameservers search := cfg.Rancher.Network.DNS.Search userSetDNS := len(nameservers) > 0 || len(search) > 0 diff --git a/init/init.go b/init/init.go index 4b61ee6f..3e735a51 100755 --- a/init/init.go +++ b/init/init.go @@ -13,6 +13,8 @@ import ( "syscall" "github.com/docker/docker/pkg/mount" + "github.com/rancher/os/cmd/control" + //networkCmd "github.com/rancher/os/cmd/network" "github.com/rancher/os/config" "github.com/rancher/os/dfs" "github.com/rancher/os/log" @@ -302,6 +304,11 @@ func RunInit() error { log.Error(err) } + if err := control.UdevSettle(); err != nil { + log.Errorf("Failed to run udev settle: %v", err) + } + + log.Debug("init: runCloudInitServices()") if err := runCloudInitServices(cfg); err != nil { log.Error(err) } diff --git a/netconf/netconf_linux.go b/netconf/netconf_linux.go index 30015fca..253b876a 100755 --- a/netconf/netconf_linux.go +++ b/netconf/netconf_linux.go @@ -193,21 +193,21 @@ func RunDhcp(netCfg *NetworkConfig, setHostname, setDNS bool) error { return err } - dhcpLinks := map[string]string{} - for _, link := range links { - if match, ok := findMatch(link, netCfg); ok && match.DHCP { - dhcpLinks[link.Attrs().Name] = match.DHCPArgs - } - } - - //run dhcp wg := sync.WaitGroup{} - for iface, args := range dhcpLinks { + + for _, link := range links { + name := link.Attrs().Name + args := "" + if match, ok := findMatch(link, netCfg); ok && match.DHCP { + args = match.DHCPArgs + } else { + args = "dhcpd --release" + } wg.Add(1) go func(iface, args string) { runDhcp(netCfg, iface, args, setHostname, setDNS) wg.Done() - }(iface, args) + }(name, args) } wg.Wait() @@ -215,7 +215,6 @@ func RunDhcp(netCfg *NetworkConfig, setHostname, setDNS bool) error { } func runDhcp(netCfg *NetworkConfig, iface string, argstr string, setHostname, setDNS bool) { - log.Infof("Running DHCP on %s", iface) args := []string{} if argstr != "" { var err error @@ -238,6 +237,7 @@ func runDhcp(netCfg *NetworkConfig, iface string, argstr string, setHostname, se args = append(args, iface) cmd := exec.Command(args[0], args[1:]...) + log.Infof("Running DHCP on %s: %s", iface, strings.Join(args, " ")) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { diff --git a/tests/assets/multi_nic/cloud-config.yml b/tests/assets/multi_nic/cloud-config.yml index 41f7bd05..c1de77b1 100644 --- a/tests/assets/multi_nic/cloud-config.yml +++ b/tests/assets/multi_nic/cloud-config.yml @@ -3,11 +3,13 @@ rancher: network: interfaces: eth0: + dhcp: true + eth1: address: 10.1.0.41/24 gateway: 10.1.0.1 mtu: 1500 dhcp: false - eth1: + eth2: address: 10.31.168.85/24 gateway: 10.31.168.1 gateway_ipv6: "fe00:1234::" diff --git a/tests/network_from_url_test.go b/tests/network_from_url_test.go index 1effaa39..a3917eb8 100644 --- a/tests/network_from_url_test.go +++ b/tests/network_from_url_test.go @@ -4,7 +4,7 @@ import . "gopkg.in/check.v1" func (s *QemuSuite) TestNetworkFromUrl(c *C) { netArgs := []string{"-net", "nic,vlan=0,model=virtio"} - args := []string{"--append", "rancher.cloud_init.datasources=[url:https://gist.githubusercontent.com/joshwget/0bdc616cd26162ad87c535644c8b1ef6/raw/8cce947c08cf006e932b71d92ddbb96bae8e3325/gistfile1.txt]"} + args := []string{"--append", "rancher.debug=true rancher.password=test-me rancher.cloud_init.datasources=[url:https://gist.githubusercontent.com/joshwget/0bdc616cd26162ad87c535644c8b1ef6/raw/8cce947c08cf006e932b71d92ddbb96bae8e3325/gistfile1.txt]"} for i := 0; i < 7; i++ { args = append(args, netArgs...) } diff --git a/tests/network_test.go b/tests/network_test.go index 35c57e45..a6aac37b 100755 --- a/tests/network_test.go +++ b/tests/network_test.go @@ -36,6 +36,107 @@ SCRIPT sudo bash test-merge`) } +func (s *QemuSuite) TestNetworkBootCfg(c *C) { + args := []string{"--append", "rancher.network.interfaces.eth1.address=10.1.0.41/24 rancher.network.interfaces.eth1.gateway=10.1.0.1 rancher.network.interfaces.eth0.dhcp=true"} + args = append(args, []string{"-net", "nic,vlan=1,model=virtio"}...) + args = append(args, []string{"-net", "nic,vlan=1,model=virtio"}...) + args = append(args, []string{"-net", "nic,vlan=0,model=virtio"}...) + s.RunQemu(c, args...) + s.CheckOutput(c, + "1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1\n"+ + " link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n"+ + " inet 127.0.0.1/8 scope host lo\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 ::1/128 scope host \n"+ + " valid_lft forever preferred_lft forever\n"+ + "2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n"+ + " inet XX.XX.XX.XX/24 brd 10.0.2.255 scope global eth0\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 fe80::5054:ff:fe12:3456/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + "3: eth1: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n"+ + " inet 10.1.0.41/24 scope global eth1\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 fe80::5054:ff:fe12:3457/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + "4: eth2: mtu 1500 qdisc noop state DOWN group default qlen 1000\n"+ + "5: eth3: mtu 1500 qdisc noop state DOWN group default qlen 1000\n"+ + "6: docker-sys: mtu 1500 qdisc noqueue state DOWN group default qlen 1000\n"+ + " inet 172.18.42.2/16 scope global docker-sys\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 XX::XX:XX:XX:XX/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + "8: docker0: XXXXXXX......\n"+ + " inet 172.17.0.1/16 scope global docker0\n"+ + " valid_lft forever preferred_lft forever\n", + Equals, + "ip a | "+ + "grep -v ether | "+ + "sed 's/inet 10\\.0\\.2\\..*\\/24 brd/inet XX.XX.XX.XX\\/24 brd/' | "+ + "sed 's/8: docker0: .*/8: docker0: XXXXXXX....../g' | "+ + "sed '/inet6 fe80::5054:ff:fe12:.*\\/64/!s/inet6 .*\\/64 scope/inet6 XX::XX:XX:XX:XX\\/64 scope/'", + // fe80::18b6:9ff:fef5:be33 + ) +} + +func (s *QemuSuite) TestNetworkBootAndCloudCfg(c *C) { + args := []string{ + "--append", "rancher.network.interfaces.eth1.address=10.1.0.52/24 rancher.network.interfaces.eth1.gateway=10.1.0.1 rancher.network.interfaces.eth0.dhcp=true rancher.network.interfaces.eth3.dhcp=true", + "--cloud-config", "./tests/assets/multi_nic/cloud-config.yml", + } + args = append(args, []string{"-net", "nic,vlan=1,model=virtio"}...) + args = append(args, []string{"-net", "nic,vlan=1,model=virtio"}...) + args = append(args, []string{"-net", "nic,vlan=0,model=virtio"}...) + s.RunQemu(c, args...) + s.CheckOutput(c, + "1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1\n"+ + " link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n"+ + " inet 127.0.0.1/8 scope host lo\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 ::1/128 scope host \n"+ + " valid_lft forever preferred_lft forever\n"+ + "2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n"+ + " inet XX.XX.XX.XX/24 brd 10.0.2.255 scope global eth0\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 fe80::5054:ff:fe12:3456/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + "3: eth1: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n"+ + // This shows that the boot cmdline wins over the cloud-config + // But IIRC, the cloud-init metadata wins allowing you to use ip4ll to get the hoster's metadata + // Need a test for that (presumably once we have libmachine based tests) + " inet 10.1.0.52/24 scope global eth1\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 fe80::5054:ff:fe12:3457/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + "4: eth2: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n"+ + " inet 10.31.168.85/24 scope global eth2\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 fe80::5054:ff:fe12:3458/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + // TODO: I think it would be better if this was dhcp: false, but it could go either way + "5: eth3: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n"+ + " inet XX.XX.XX.XX/24 brd 10.0.2.255 scope global eth3\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 fe80::5054:ff:fe12:3459/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + "6: docker-sys: mtu 1500 qdisc noqueue state DOWN group default qlen 1000\n"+ + " inet 172.18.42.2/16 scope global docker-sys\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 XX::XX:XX:XX:XX/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + "8: docker0: XXXXXXX......\n"+ + " inet 172.17.0.1/16 scope global docker0\n"+ + " valid_lft forever preferred_lft forever\n", + Equals, + "ip a | "+ + "grep -v ether | "+ + "sed 's/inet 10\\.0\\.2\\..*\\/24 brd/inet XX.XX.XX.XX\\/24 brd/' | "+ + "sed 's/8: docker0: .*/8: docker0: XXXXXXX....../g' | "+ + "sed '/inet6 fe80::5054:ff:fe12:.*\\/64/!s/inet6 .*\\/64 scope/inet6 XX::XX:XX:XX:XX\\/64 scope/'", + // fe80::18b6:9ff:fef5:be33 + ) +} + func (s *QemuSuite) TestNetworkCfg(c *C) { args := []string{"--cloud-config", "./tests/assets/multi_nic/cloud-config.yml"} args = append(args, []string{"-net", "nic,vlan=1,model=virtio"}...) @@ -48,50 +149,78 @@ func (s *QemuSuite) TestNetworkCfg(c *C) { // valid_lft forever preferred_lft forever // show ip a output without mac addresses - s.CheckOutput(c, `1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 - link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 - inet 127.0.0.1/8 scope host lo - valid_lft forever preferred_lft forever - inet6 ::1/128 scope host - valid_lft forever preferred_lft forever -2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 - inet XX.XX.XX.XX/24 brd 10.0.2.255 scope global eth0 - valid_lft forever preferred_lft forever - inet 10.1.0.41/24 scope global eth0 - valid_lft forever preferred_lft forever - inet6 XX::XX:XX:XX:XX/64 scope link - valid_lft forever preferred_lft forever -3: eth1: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 - inet 10.31.168.85/24 scope global eth1 - valid_lft forever preferred_lft forever - inet6 XX::XX:XX:XX:XX/64 scope link - valid_lft forever preferred_lft forever -4: eth2: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 - inet6 XX::XX:XX:XX:XX/64 scope link - valid_lft forever preferred_lft forever -5: eth3: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 - inet XX.XX.XX.XX/24 brd 10.0.2.255 scope global eth3 - valid_lft forever preferred_lft forever - inet6 XX::XX:XX:XX:XX/64 scope link - valid_lft forever preferred_lft forever -6: docker-sys: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 - inet 172.18.42.2/16 scope global docker-sys - valid_lft forever preferred_lft forever - inet6 XX::XX:XX:XX:XX/64 scope link - valid_lft forever preferred_lft forever -8: docker0: mtu 1500 qdisc noqueue state DOWN group default - inet 172.17.0.1/16 scope global docker0 - valid_lft forever preferred_lft forever -`, Equals, "ip a | grep -v ether | sed 's/inet 10\\.0\\.2\\..*\\/24 brd/inet XX.XX.XX.XX\\/24 brd/' | sed 's/inet6 .*\\/64 scope/inet6 XX::XX:XX:XX:XX\\/64 scope/'") + s.CheckOutput(c, + "1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1\n"+ + " link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n"+ + " inet 127.0.0.1/8 scope host lo\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 ::1/128 scope host \n"+ + " valid_lft forever preferred_lft forever\n"+ + "2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n"+ + " inet XX.XX.XX.XX/24 brd 10.0.2.255 scope global eth0\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 fe80::5054:ff:fe12:3456/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + "3: eth1: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n"+ + " inet 10.1.0.41/24 scope global eth1\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 fe80::5054:ff:fe12:3457/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + "4: eth2: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n"+ + " inet 10.31.168.85/24 scope global eth2\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 fe80::5054:ff:fe12:3458/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + // TODO: I think it would be better if this was dhcp: false, but it could go either way + "5: eth3: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n"+ + " inet XX.XX.XX.XX/24 brd 10.0.2.255 scope global eth3\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 fe80::5054:ff:fe12:3459/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + "6: docker-sys: mtu 1500 qdisc noqueue state DOWN group default qlen 1000\n"+ + " inet 172.18.42.2/16 scope global docker-sys\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 XX::XX:XX:XX:XX/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n"+ + "8: docker0: XXXXXXX......\n"+ + " inet 172.17.0.1/16 scope global docker0\n"+ + " valid_lft forever preferred_lft forever\n", + Equals, + "ip a | "+ + "grep -v ether | "+ + "sed 's/inet 10\\.0\\.2\\..*\\/24 brd/inet XX.XX.XX.XX\\/24 brd/' | "+ + "sed 's/8: docker0: .*/8: docker0: XXXXXXX....../g' | "+ + "sed '/inet6 fe80::5054:ff:fe12:.*\\/64/!s/inet6 .*\\/64 scope/inet6 XX::XX:XX:XX:XX\\/64 scope/'", + // fe80::18b6:9ff:fef5:be33 + ) - s.CheckOutput(c, `Kernel IP routing table -Destination Gateway Genmask Flags Metric Ref Use Iface -0.0.0.0 10.31.168.1 0.0.0.0 UG 0 0 0 eth1 -0.0.0.0 10.0.2.2 0.0.0.0 UG 205 0 0 eth3 -10.0.2.0 0.0.0.0 255.255.255.0 U 205 0 0 eth3 -10.1.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 -10.31.168.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 -172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0 -172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker-sys -`, Equals, "route -n") + s.CheckOutput(c, + "Kernel IP routing table\n"+ + "Destination Gateway Genmask Flags Metric Ref Use Iface\n"+ + "0.0.0.0 10.1.0.1 0.0.0.0 UG 0 0 0 eth1\n"+ + "0.0.0.0 10.0.2.2 0.0.0.0 UG 202 0 0 eth0\n"+ + "0.0.0.0 10.0.2.2 0.0.0.0 UG 205 0 0 eth3\n"+ + "10.0.2.0 0.0.0.0 255.255.255.0 U 202 0 0 eth0\n"+ + "10.0.2.0 0.0.0.0 255.255.255.0 U 205 0 0 eth3\n"+ + "10.1.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1\n"+ + "10.31.168.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2\n"+ + "172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0\n"+ + "172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker-sys\n", + Equals, "route -n") + + s.CheckCall(c, "sudo ros config set rancher.network.interfaces.eth3.dhcp true") + //s.CheckCall(c, "sudo netconf") + s.Reboot(c) + s.CheckOutput(c, + "5: eth3: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n"+ + " inet XX.XX.XX.XX/24 brd 10.0.2.255 scope global eth3\n"+ + " valid_lft forever preferred_lft forever\n"+ + " inet6 fe80::5054:ff:fe12:3459/64 scope link \n"+ + " valid_lft forever preferred_lft forever\n", + Equals, + "ip a show eth3 | "+ + "grep -v ether | "+ + "sed 's/inet 10\\.0\\.2\\..*\\/24 brd/inet XX.XX.XX.XX\\/24 brd/' | "+ + "sed '/inet6 fe80::5054:ff:fe12:.*\\/64/!s/inet6 .*\\/64 scope/inet6 XX::XX:XX:XX:XX\\/64 scope/'", + ) }