diff --git a/cmd/cloudinitsave/cloudinitsave.go b/cmd/cloudinitsave/cloudinitsave.go index 80df80b2..6f188740 100755 --- a/cmd/cloudinitsave/cloudinitsave.go +++ b/cmd/cloudinitsave/cloudinitsave.go @@ -272,7 +272,7 @@ func enableDoLinkLocal() { IPV4LL: true, }, }, - }) + }, false, false) if err != nil { log.Errorf("Failed to apply link local on eth0: %v", err) } diff --git a/cmd/network/network.go b/cmd/network/network.go index 0cd8b5e3..57d0aa4b 100755 --- a/cmd/network/network.go +++ b/cmd/network/network.go @@ -51,14 +51,8 @@ func ApplyNetworkConfig(cfg *config.CloudConfig) { log.Error(err) } - if err := netconf.ApplyNetworkConfigs(&cfg.Rancher.Network); err != nil { - log.Error(err) - } - - // TODO: seems wrong to do this outside netconf userSetHostname := cfg.Hostname != "" - log.Infof("Apply Network Config RunDhcp") - if err := netconf.RunDhcp(&cfg.Rancher.Network, !userSetHostname, !userSetDNS); err != nil { + if err := netconf.ApplyNetworkConfigs(&cfg.Rancher.Network, userSetHostname, userSetDNS); err != nil { log.Error(err) } diff --git a/dfs/scratch.go b/dfs/scratch.go index cb89c2c3..04b655f8 100644 --- a/dfs/scratch.go +++ b/dfs/scratch.go @@ -373,7 +373,7 @@ ff02::2 ip6-allrouters Bridge: "true", }, }, - }); err != nil { + }, false, false); err != nil { return err } } diff --git a/docs/os/networking/interfaces/index.md b/docs/os/networking/interfaces/index.md index 7dcab992..032ee3e4 100644 --- a/docs/os/networking/interfaces/index.md +++ b/docs/os/networking/interfaces/index.md @@ -111,3 +111,58 @@ rancher: eth0: bridge: br0 ``` + +### Run custom network configuration commands + +You can configure `pre` and `post` network configuration commands to run in the `network` service container by adding `pre_cmds` and `post_cmds` array keys to `rancher.network`, or `pre_up` and`post_up` keys for specific `rancher.network.interfaces`. + +For example: + +``` +#cloud-config +write_files: + - container: network + path: /var/lib/iptables/rules.sh + permissions: "0755" + owner: root:root + content: | + #!/bin/bash + set -ex + echo $@ >> /var/log/net.log + # the last line of the file needs to be a blank line or a comment +rancher: + network: + dns: + nameservers: + - 8.8.4.4 + - 4.2.2.3 + pre_cmds: + - /var/lib/iptables/rules.sh pre_cmds + post_cmds: + - /var/lib/iptables/rules.sh post_cmds + interfaces: + lo: + pre_up: + - /var/lib/iptables/rules.sh pre_up lo + post_up: + - /var/lib/iptables/rules.sh post_up lo + eth0: + pre_up: + - /var/lib/iptables/rules.sh pre_up eth0 + post_up: + - /var/lib/iptables/rules.sh post_up eth0 + eth1: + dhcp: true + pre_up: + - /var/lib/iptables/rules.sh pre_up eth1 + post_up: + - /var/lib/iptables/rules.sh post_up eth1 + eth2: + address: 192.168.3.13/16 + mtu: 1450 + pre_up: + - /var/lib/iptables/rules.sh pre_up eth2 + post_up: + - /var/lib/iptables/rules.sh post_up eth2 +``` + diff --git a/netconf/netconf_linux.go b/netconf/netconf_linux.go index d8b7d8f2..e6a79612 100755 --- a/netconf/netconf_linux.go +++ b/netconf/netconf_linux.go @@ -157,14 +157,14 @@ func populateDefault(netCfg *NetworkConfig) { } } -func ApplyNetworkConfigs(netCfg *NetworkConfig) error { +func ApplyNetworkConfigs(netCfg *NetworkConfig, userSetHostname, userSetDNS bool) error { populateDefault(netCfg) log.Debugf("Config: %#v", netCfg) runCmds(netCfg.PreCmds, "") + defer runCmds(netCfg.PostCmds, "") createInterfaces(netCfg) - createSlaveInterfaces(netCfg) links, err := netlink.LinkList() @@ -172,58 +172,54 @@ func ApplyNetworkConfigs(netCfg *NetworkConfig) error { return err } - //apply network config - for _, link := range links { - linkName := link.Attrs().Name - if match, ok := findMatch(link, netCfg); ok && !match.DHCP { - if err := applyInterfaceConfig(link, match); err != nil { - log.Errorf("Failed to apply settings to %s : %v", linkName, err) - } - } - } - - runCmds(netCfg.PostCmds, "") - return err -} - -func RunDhcp(netCfg *NetworkConfig, setHostname, setDNS bool) error { - log.Debugf("RunDhcp(%V, %v)", setHostname, setDNS) - populateDefault(netCfg) - - links, err := netlink.LinkList() - if err != nil { - log.Errorf("RunDhcp failed to get LinkList, %s", err) - return err - } - wg := sync.WaitGroup{} + //apply network config for _, link := range links { - name := link.Attrs().Name - if name == "lo" { - continue - } - match, ok := findMatch(link, netCfg) - if !ok { - continue - } - wg.Add(1) - go func(iface string, match InterfaceConfig) { - if match.DHCP { - // retrigger, perhaps we're running this to get the new address - runDhcp(netCfg, iface, match.DHCPArgs, setHostname, setDNS) - } else { - if hasDhcp(iface) { - log.Infof("dhcp release %s", iface) - runDhcp(netCfg, iface, dhcpReleaseCmd, false, true) - } - } - wg.Done() - }(name, match) + applyOuter(link, netCfg, wg, userSetHostname, userSetDNS) } wg.Wait() - return nil + return err +} + +func applyOuter(link netlink.Link, netCfg *NetworkConfig, wg sync.WaitGroup, userSetHostname, userSetDNS bool) { + log.Debugf("applyOuter(%V, %v)", userSetHostname, userSetDNS) + match, ok := findMatch(link, netCfg) + if !ok { + return + } + + linkName := link.Attrs().Name + + log.Debugf("Config(%s): %#v", linkName, match) + runCmds(match.PreUp, linkName) + defer runCmds(match.PostUp, linkName) + + if !match.DHCP { + if err := applyInterfaceConfig(link, match); err != nil { + log.Errorf("Failed to apply settings to %s : %v", linkName, err) + } + } + if linkName == "lo" { + return + } + if !match.DHCP && !hasDhcp(linkName) { + log.Debugf("Skipping(%s): DHCP=false && no DHCP lease yet", linkName) + return + } + + wg.Add(1) + go func(iface string, match InterfaceConfig) { + if match.DHCP { + // retrigger, perhaps we're running this to get the new address + runDhcp(netCfg, iface, match.DHCPArgs, !userSetHostname, !userSetDNS) + } else { + log.Infof("dhcp release %s", iface) + runDhcp(netCfg, iface, dhcpReleaseCmd, false, true) + } + wg.Done() + }(linkName, match) } func hasDhcp(iface string) bool { @@ -434,8 +430,6 @@ func applyInterfaceConfig(link netlink.Link, netConf InterfaceConfig) error { } } - runCmds(netConf.PreUp, link.Attrs().Name) - if err := linkUp(link, netConf); err != nil { return err } @@ -450,13 +444,13 @@ func applyInterfaceConfig(link netlink.Link, netConf InterfaceConfig) error { } // TODO: how to remove a GW? (on aws it seems to be hard to find out what the gw is :/) - runCmds(netConf.PostUp, link.Attrs().Name) - return nil } func runCmds(cmds []string, iface string) { + log.Debugf("runCmds(on %s): %v", iface, cmds) for _, cmd := range cmds { + log.Debugf("runCmd(on %s): %v", iface, cmd) cmd = strings.TrimSpace(cmd) if cmd == "" { continue diff --git a/scripts/build b/scripts/build index ec88e1e5..118906ee 100755 --- a/scripts/build +++ b/scripts/build @@ -1,5 +1,7 @@ #!/bin/bash set -e +echo -------------------------./build-target $(dirname $0)/build-target +echo -------------------------./build-host $(dirname $0)/build-host diff --git a/scripts/build-target b/scripts/build-target index 0cba8443..b7e9d3fe 100755 --- a/scripts/build-target +++ b/scripts/build-target @@ -1,5 +1,5 @@ #!/bin/bash -set -e +set -ex ros="$1" diff --git a/scripts/dev b/scripts/dev index 0753136a..1ef091a2 100755 --- a/scripts/dev +++ b/scripts/dev @@ -4,6 +4,9 @@ set -e cd $(dirname $0) +echo ------------------------ ./build ./build +echo ------------------------ ./prepare ./prepare +echo ------------------------ ./package ROOTFS=0 ./package diff --git a/tests/assets/pre_cmds/cloud-config.yml b/tests/assets/pre_cmds/cloud-config.yml new file mode 100644 index 00000000..376001de --- /dev/null +++ b/tests/assets/pre_cmds/cloud-config.yml @@ -0,0 +1,47 @@ +#cloud-config +write_files: + - container: network + path: /var/lib/iptables/rules.sh + permissions: "0755" + owner: root:root + content: | + #!/bin/bash + set -ex + echo $@ >> /var/log/net.log + # the last line of the file needs to be a blank line or a comment +rancher: + network: + dns: + nameservers: + - 8.8.4.4 + - 4.2.2.3 + pre_cmds: + - /var/lib/iptables/rules.sh pre_cmds + post_cmds: + - /var/lib/iptables/rules.sh post_cmds + interfaces: + lo: + pre_up: + - /var/lib/iptables/rules.sh pre_up lo + post_up: + - /var/lib/iptables/rules.sh post_up lo + eth0: + pre_up: + - /var/lib/iptables/rules.sh pre_up eth0 + post_up: + - /var/lib/iptables/rules.sh post_up eth0 + eth1: + dhcp: true + pre_up: + - /var/lib/iptables/rules.sh pre_up eth1 + post_up: + - /var/lib/iptables/rules.sh post_up eth1 + eth2: + address: 192.168.3.13/16 + mtu: 1450 + pre_up: + - /var/lib/iptables/rules.sh pre_up eth2 + post_up: + - /var/lib/iptables/rules.sh post_up eth2 +ssh_authorized_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC85w9stZyiLQp/DkVO6fqwiShYcj1ClKdtCqgHtf+PLpJkFReSFu8y21y+ev09gsSMRRrjF7yt0pUHV6zncQhVeqsZtgc5WbELY2DOYUGmRn/CCvPbXovoBrQjSorqlBmpuPwsStYLr92Xn+VVsMNSUIegHY22DphGbDKG85vrKB8HxUxGIDxFBds/uE8FhSy+xsoyT/jUZDK6pgq2HnGl6D81ViIlKecpOpWlW3B+fea99ADNyZNVvDzbHE5pcI3VRw8u59WmpWOUgT6qacNVACl8GqpBvQk8sw7O/X9DSZHCKafeD9G5k+GYbAUz92fKWrx/lOXfUXPS3+c8dRIF diff --git a/tests/network_test.go b/tests/network_test.go index 11e4ad63..d9c4d234 100755 --- a/tests/network_test.go +++ b/tests/network_test.go @@ -222,3 +222,27 @@ func (s *QemuSuite) TestNetworkCfg(c *C) { "sed '/inet6 fe80::5054:ff:fe12:.*\\/64/!s/inet6 .*\\/64 scope/inet6 XX::XX:XX:XX:XX\\/64 scope/'", ) } + +func (s *QemuSuite) TestNetworkCmds(c *C) { + args := []string{ + "--cloud-config", + "tests/assets/pre_cmds/cloud-config.yml", + "-net", "nic,vlan=0,model=virtio", + "-net", "nic,vlan=1,model=virtio", + } + s.RunQemuWithNetConsole(c, args...) + s.NetCheckOutput(c, + "pre_cmds\n"+ + "pre_up lo\n"+ + "post_up lo\n"+ + "pre_up eth0\n"+ + "post_up eth0\n"+ + "pre_up eth1\n"+ + "post_up eth1\n"+ + "pre_up eth2\n"+ + "post_up eth2\n"+ + "post_cmds\n", + Equals, + "cat /var/log/net.log", + ) +}