From 6cf84c7dc6f46e30d411abd2fac182800f27b8ed Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Tue, 22 Dec 2015 21:50:04 -0700 Subject: [PATCH] Bump vendored netconf --- glide.yaml | 2 +- vendor/github.com/rancher/netconf/bonding.go | 129 ++++++++++++ .../rancher/netconf/netconf_linux.go | 183 +++++++++++++++--- vendor/github.com/rancher/netconf/types.go | 20 +- 4 files changed, 295 insertions(+), 39 deletions(-) create mode 100644 vendor/github.com/rancher/netconf/bonding.go diff --git a/glide.yaml b/glide.yaml index 8d487796..3e9db80e 100644 --- a/glide.yaml +++ b/glide.yaml @@ -69,7 +69,7 @@ import: version: 1.9.1-2 - package: github.com/rancher/netconf - version: 02925e7cf5a0f0bb0aa5360ee260ef7378e5eff8 + version: 8080e4909627bbdf51d7f427211a7c0517136373 - package: github.com/ryanuber/go-glob version: 0067a9abd927e50aed5190662702f81231413ae0 diff --git a/vendor/github.com/rancher/netconf/bonding.go b/vendor/github.com/rancher/netconf/bonding.go new file mode 100644 index 00000000..b57dc011 --- /dev/null +++ b/vendor/github.com/rancher/netconf/bonding.go @@ -0,0 +1,129 @@ +package netconf + +import ( + "io/ioutil" + "os" + "os/exec" + "strings" + "time" + + "github.com/Sirupsen/logrus" + "github.com/vishvananda/netlink" +) + +const ( + base = "/sys/class/net/" + bondingMasters = "/sys/class/net/bonding_masters" +) + +type Bonding struct { + err error + name string +} + +func (b *Bonding) Error() error { + return b.err +} + +func (b *Bonding) init() { + _, err := os.Stat(bondingMasters) + if os.IsNotExist(err) { + logrus.Info("Loading bonding kernel module") + cmd := exec.Command("modprobe", "bonding") + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdin + b.err = cmd.Run() + if b.err != nil { + for i := 0; i < 30; i++ { + if _, err := os.Stat(bondingMasters); err == nil { + break + } + time.Sleep(100 * time.Millisecond) + } + } + } + _, err = os.Stat(bondingMasters) + if err != nil { + b.err = err + } +} + +func contains(file, word string) (bool, error) { + words, err := ioutil.ReadFile(file) + if err != nil { + return false, err + } + + for _, s := range strings.Split(strings.TrimSpace(string(words)), " ") { + if s == strings.TrimSpace(word) { + return true, nil + } + } + + return false, nil +} + +func (b *Bonding) AddSlave(slave string) { + if b.err != nil { + return + } + + if ok, err := contains(base+b.name+"/bonding/slaves", slave); err != nil { + b.err = err + return + } else if ok { + return + } + + link, err := netlink.LinkByName(slave) + if err != nil { + b.err = err + return + } + + b.err = netlink.LinkSetDown(link) + if b.err != nil { + return + } + + p := base + b.name + "/bonding/slaves" + logrus.Infof("Adding slave %s to master %s", slave, b.name) + b.err = ioutil.WriteFile(p, []byte("+"+slave), 0644) +} + +func (b *Bonding) Opt(key, value string) { + if b.err != nil { + return + } + + p := base + b.name + "/bonding/" + key + b.err = ioutil.WriteFile(p, []byte(value), 0644) + if b.err != nil { + logrus.Errorf("Failed to set %s=%s on %s", key, value, b.name) + } else { + logrus.Infof("Set %s=%s on %s", key, value, b.name) + } +} + +func (b *Bonding) Clear() { + b.err = nil +} + +func Bond(name string) *Bonding { + b := &Bonding{name: name} + b.init() + if b.err != nil { + return b + } + + if ok, err := contains(bondingMasters, name); err != nil { + b.err = err + return b + } else if ok { + return b + } + + logrus.Infof("Creating bond %s", name) + b.err = ioutil.WriteFile(bondingMasters, []byte("+"+name), 0644) + return b +} diff --git a/vendor/github.com/rancher/netconf/netconf_linux.go b/vendor/github.com/rancher/netconf/netconf_linux.go index 4170551e..8ce44072 100644 --- a/vendor/github.com/rancher/netconf/netconf_linux.go +++ b/vendor/github.com/rancher/netconf/netconf_linux.go @@ -3,36 +3,83 @@ package netconf import ( "bytes" "errors" + "io/ioutil" "net" "os" "os/exec" "strings" + "syscall" log "github.com/Sirupsen/logrus" + "github.com/flynn/go-shlex" "github.com/ryanuber/go-glob" "github.com/vishvananda/netlink" ) +const ( + CONF = "/var/lib/rancher/conf" + NET_SCRIPT = "/var/lib/rancher/conf/network.sh" +) + func createInterfaces(netCfg *NetworkConfig) error { for name, iface := range netCfg.Interfaces { - if !iface.Bridge { - continue - } + if iface.Bridge { + bridge := netlink.Bridge{} + bridge.LinkAttrs.Name = name - bridge := netlink.Bridge{} - bridge.LinkAttrs.Name = name + if err := netlink.LinkAdd(&bridge); err != nil { + log.Errorf("Failed to create bridge %s: %v", name, err) + } + } else if iface.Bond != "" { + bondIface, ok := netCfg.Interfaces[iface.Bond] + if !ok { + log.Errorf("Failed to find bond configuration for [%s]", iface.Bond) + continue + } + bond := Bond(iface.Bond) + if bond.Error() != nil { + log.Errorf("Failed to create bond [%s]: %v", iface.Bond, bond.Error()) + continue + } - if err := netlink.LinkAdd(&bridge); err != nil { - log.Errorf("Failed to create bridge %s: %v", name, err) + for k, v := range bondIface.BondOpts { + bond.Opt(k, v) + bond.Clear() + } } } return nil } +func runScript(netCfg *NetworkConfig) error { + if netCfg.Script == "" { + return nil + } + + if _, err := os.Stat(CONF); os.IsNotExist(err) { + if err := os.MkdirAll(CONF, 0700); err != nil { + return err + } + } + + if err := ioutil.WriteFile(NET_SCRIPT, []byte(netCfg.Script), 0700); err != nil { + return err + } + + cmd := exec.Command(NET_SCRIPT) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + func ApplyNetworkConfigs(netCfg *NetworkConfig) error { log.Debugf("Config: %#v", netCfg) + if err := runScript(netCfg); err != nil { + log.Errorf("Failed to run script: %v", err) + } + if err := createInterfaces(netCfg); err != nil { return err } @@ -63,7 +110,8 @@ func ApplyNetworkConfigs(netCfg *NetworkConfig) error { if err != nil { return err } - if bytes.Compare(haAddr, link.Attrs().HardwareAddr) == 0 { + // Don't match mac address of the bond because it is the same as the slave + if bytes.Compare(haAddr, link.Attrs().HardwareAddr) == 0 && link.Attrs().Name != netConf.Bond { // MAC address match is used over all other matches match = netConf break @@ -108,24 +156,87 @@ func ApplyNetworkConfigs(netCfg *NetworkConfig) error { return nil } +func linkUp(link netlink.Link, netConf InterfaceConfig) error { + if err := netlink.LinkSetUp(link); err != nil { + log.Errorf("failed to setup link: %v", err) + return err + } + + return nil +} + +func applyAddress(address string, link netlink.Link, netConf InterfaceConfig) error { + addr, err := netlink.ParseAddr(address) + if err != nil { + return err + } + if err := netlink.AddrAdd(link, addr); err == syscall.EEXIST { + //Ignore this error + } else if err != nil { + log.Errorf("addr add failed: %v", err) + } else { + log.Infof("Set %s on %s", netConf.Address, link.Attrs().Name) + } + + return nil +} + +func setGateway(gateway string) error { + if gateway == "" { + return nil + } + + gatewayIp := net.ParseIP(gateway) + if gatewayIp == nil { + return errors.New("Invalid gateway address " + gateway) + } + + route := netlink.Route{ + Scope: netlink.SCOPE_UNIVERSE, + Gw: gatewayIp, + } + + if err := netlink.RouteAdd(&route); err == syscall.EEXIST { + //Ignore this error + } else if err != nil { + log.Errorf("gateway set failed: %v", err) + return err + } + + log.Infof("Set default gateway %s", gateway) + return nil +} + func applyNetConf(link netlink.Link, netConf InterfaceConfig) error { + if netConf.Bond != "" { + b := Bond(netConf.Bond) + b.AddSlave(link.Attrs().Name) + if b.Error() != nil { + return b.Error() + } + + return linkUp(link, netConf) + } + if netConf.IPV4LL { if err := AssignLinkLocalIP(link); err != nil { log.Errorf("IPV4LL set failed: %v", err) return err } - } else if netConf.Address == "" { + } else if netConf.Address == "" && len(netConf.Addresses) == 0 { return nil } else { - addr, err := netlink.ParseAddr(netConf.Address) - if err != nil { - return err + if netConf.Address != "" { + err := applyAddress(netConf.Address, link, netConf) + if err != nil { + log.Errorf("Failed to apply address %s to %s: %v", netConf.Address, link.Attrs().Name, err) + } } - if err := netlink.AddrAdd(link, addr); err != nil { - //Ignore this error - log.Errorf("addr add failed: %v", err) - } else { - log.Infof("Set %s on %s", netConf.Address, link.Attrs().Name) + for _, address := range netConf.Addresses { + err := applyAddress(address, link, netConf) + if err != nil { + log.Errorf("Failed to apply address %s to %s: %v", address, link.Attrs().Name, err) + } } } @@ -136,27 +247,37 @@ func applyNetConf(link netlink.Link, netConf InterfaceConfig) error { } } - if err := netlink.LinkSetUp(link); err != nil { - log.Errorf("failed to setup link: %v", err) + if err := linkUp(link, netConf); err != nil { return err } - if netConf.Gateway != "" { - gatewayIp := net.ParseIP(netConf.Gateway) - if gatewayIp == nil { - return errors.New("Invalid gateway address " + netConf.Gateway) + if err := setGateway(netConf.Gateway); err != nil { + log.Errorf("Fail to set gateway %s", netConf.Gateway) + } + + if err := setGateway(netConf.GatewayIpv6); err != nil { + log.Errorf("Fail to set gateway %s", netConf.Gateway) + } + + for _, postUp := range netConf.PostUp { + postUp = strings.TrimSpace(postUp) + if postUp == "" { + continue } - route := netlink.Route{ - Scope: netlink.SCOPE_UNIVERSE, - Gw: net.ParseIP(netConf.Gateway), - } - if err := netlink.RouteAdd(&route); err != nil { - log.Errorf("gateway set failed: %v", err) - return err + args, err := shlex.Split(strings.Replace(postUp, "$iface", link.Attrs().Name, -1)) + if err != nil { + log.Errorf("Failed to parse command [%s]: %v", postUp, err) + continue } - log.Infof("Set default gateway %s", netConf.Gateway) + cmd := exec.Command(args[0], args[1:]...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + log.Errorf("Failed to run command [%s]: %v", postUp, err) + continue + } } return nil diff --git a/vendor/github.com/rancher/netconf/types.go b/vendor/github.com/rancher/netconf/types.go index e07d2cd9..2b86e2ca 100644 --- a/vendor/github.com/rancher/netconf/types.go +++ b/vendor/github.com/rancher/netconf/types.go @@ -1,18 +1,24 @@ package netconf type NetworkConfig struct { + Script string `yaml:"script,omitempty"` Dns DnsConfig `yaml:"dns,omitempty"` Interfaces map[string]InterfaceConfig `yaml:"interfaces,omitempty"` } type InterfaceConfig struct { - Match string `yaml:"match,omitempty"` - DHCP bool `yaml:"dhcp,omitempty"` - Address string `yaml:"address,omitempty"` - IPV4LL bool `yaml:"ipv4ll,omitempty"` - Gateway string `yaml:"gateway,omitempty"` - MTU int `yaml:"mtu,omitempty"` - Bridge bool `yaml:"bridge,omitempty"` + Match string `yaml:"match,omitempty"` + DHCP bool `yaml:"dhcp,omitempty"` + Address string `yaml:"address,omitempty"` + Addresses []string `yaml:"addresses,omitempty"` + IPV4LL bool `yaml:"ipv4ll,omitempty"` + Gateway string `yaml:"gateway,omitempty"` + GatewayIpv6 string `yaml:"gateway_ipv6,omitempty"` + MTU int `yaml:"mtu,omitempty"` + Bridge bool `yaml:"bridge,omitempty"` + Bond string `yaml:"bond,omitempty"` + BondOpts map[string]string `yaml:"bond_opts,omitempty"` + PostUp []string `yaml:"post_up,omitempty"` } type DnsConfig struct {