1
0
mirror of https://github.com/rancher/os.git synced 2025-06-25 22:41:36 +00:00
os/netconf/bonding.go
Sven Dowideit 4df962d4b6 make ros log to dmesg
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2016-11-30 10:51:30 +10:00

144 lines
2.9 KiB
Go

package netconf
import (
"io/ioutil"
"os"
"os/exec"
"strings"
"time"
"github.com/rancher/os/log"
"github.com/vishvananda/netlink"
)
const (
base = "/sys/class/net/"
bondingMasters = "/sys/class/net/bonding_masters"
)
type Bonding struct {
name string
}
func (b *Bonding) init() error {
_, err := os.Stat(bondingMasters)
if os.IsNotExist(err) {
log.Info("Loading bonding kernel module")
cmd := exec.Command("modprobe", "bonding")
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdin
err = cmd.Run()
if 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)
return 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) linkDown() error {
link, err := netlink.LinkByName(b.name)
if err != nil {
return err
}
return netlink.LinkSetDown(link)
}
func (b *Bonding) ListSlaves() ([]string, error) {
file := base + b.name + "/bonding/slaves"
words, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}
result := []string{}
for _, s := range strings.Split(strings.TrimSpace(string(words)), " ") {
if s != "" {
result = append(result, s)
}
}
return result, nil
}
func (b *Bonding) RemoveSlave(slave string) error {
if ok, err := contains(base+b.name+"/bonding/slaves", slave); err != nil {
return err
} else if !ok {
return nil
}
p := base + b.name + "/bonding/slaves"
log.Infof("Removing slave %s from master %s", slave, b.name)
return ioutil.WriteFile(p, []byte("-"+slave), 0644)
}
func (b *Bonding) AddSlave(slave string) error {
if ok, err := contains(base+b.name+"/bonding/slaves", slave); err != nil {
return err
} else if ok {
return nil
}
p := base + b.name + "/bonding/slaves"
log.Infof("Adding slave %s to master %s", slave, b.name)
return ioutil.WriteFile(p, []byte("+"+slave), 0644)
}
func (b *Bonding) Opt(key, value string) error {
if key == "mode" {
// Don't care about errors here
b.linkDown()
slaves, _ := b.ListSlaves()
for _, slave := range slaves {
b.RemoveSlave(slave)
}
}
p := base + b.name + "/bonding/" + key
if err := ioutil.WriteFile(p, []byte(value), 0644); err != nil {
log.Errorf("Failed to set %s=%s on %s: %v", key, value, b.name, err)
return err
}
log.Infof("Set %s=%s on %s", key, value, b.name)
return nil
}
func Bond(name string) (*Bonding, error) {
b := &Bonding{name: name}
if err := b.init(); err != nil {
return nil, err
}
if ok, err := contains(bondingMasters, name); err != nil {
return nil, err
} else if ok {
return b, nil
}
log.Infof("Creating bond %s", name)
return b, ioutil.WriteFile(bondingMasters, []byte("+"+name), 0644)
}