diff options
author | Ritu Sood <ritu.sood@intel.com> | 2018-11-10 09:56:52 -0800 |
---|---|---|
committer | Victor Morales <victor.morales@intel.com> | 2018-11-20 01:50:58 -0800 |
commit | 5026d1d89b05eac5e004279b742df6745a73d93a (patch) | |
tree | 8f9aed1e476706e008b746debda6d616bd0ac7a5 /internal/pkg/util | |
parent | 9506ae48eb545d502cc3685a99862740d28e7afb (diff) |
Seed code for the Plugin
The code includes ovn4nfvk8s Plugin & CNI. It implements multiple OVN
interfaces for Pods and assumes Multus (or similar CNI) calls its CNI
not as first CNI.
Change-Id: I524c1d18752eb6dbc8d34addd3b60d5bbaa06ff4
Signed-off-by: Ritu Sood <ritu.sood@intel.com>
Signed-off-by: Victor Morales <victor.morales@intel.com>
Diffstat (limited to 'internal/pkg/util')
-rw-r--r-- | internal/pkg/util/.gitkeep | 0 | ||||
-rw-r--r-- | internal/pkg/util/net.go | 34 | ||||
-rw-r--r-- | internal/pkg/util/ovs.go | 126 |
3 files changed, 160 insertions, 0 deletions
diff --git a/internal/pkg/util/.gitkeep b/internal/pkg/util/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/internal/pkg/util/.gitkeep +++ /dev/null diff --git a/internal/pkg/util/net.go b/internal/pkg/util/net.go new file mode 100644 index 0000000..1ff7fbb --- /dev/null +++ b/internal/pkg/util/net.go @@ -0,0 +1,34 @@ +package util + +import ( + "fmt" + "math/big" + "math/rand" + "net" + "time" +) + +// GenerateMac generates mac address. +func GenerateMac() string { + prefix := "00:00:00" + newRand := rand.New(rand.NewSource(time.Now().UnixNano())) + mac := fmt.Sprintf("%s:%02x:%02x:%02x", prefix, newRand.Intn(255), newRand.Intn(255), newRand.Intn(255)) + return mac +} + +// NextIP returns IP incremented by 1 +func NextIP(ip net.IP) net.IP { + i := ipToInt(ip) + return intToIP(i.Add(i, big.NewInt(1))) +} + +func ipToInt(ip net.IP) *big.Int { + if v := ip.To4(); v != nil { + return big.NewInt(0).SetBytes(v) + } + return big.NewInt(0).SetBytes(ip.To16()) +} + +func intToIP(i *big.Int) net.IP { + return net.IP(i.Bytes()) +} diff --git a/internal/pkg/util/ovs.go b/internal/pkg/util/ovs.go new file mode 100644 index 0000000..22b42b9 --- /dev/null +++ b/internal/pkg/util/ovs.go @@ -0,0 +1,126 @@ +package util + +import ( + "bytes" + "fmt" + "strings" + "time" + "unicode" + + "github.com/sirupsen/logrus" + kexec "k8s.io/utils/exec" +) + +const ( + ovsCommandTimeout = 15 + ovsVsctlCommand = "ovs-vsctl" + ovsOfctlCommand = "ovs-ofctl" + ovnNbctlCommand = "ovn-nbctl" + ipCommand = "ip" +) + +// Exec runs various OVN and OVS utilities +type execHelper struct { + exec kexec.Interface + ofctlPath string + vsctlPath string + nbctlPath string + ipPath string +} + +var runner *execHelper + +// SetExec validates executable paths and saves the given exec interface +// to be used for running various OVS and OVN utilites +func SetExec(exec kexec.Interface) error { + var err error + + runner = &execHelper{exec: exec} + runner.ofctlPath, err = exec.LookPath(ovsOfctlCommand) + if err != nil { + return err + } + runner.vsctlPath, err = exec.LookPath(ovsVsctlCommand) + if err != nil { + return err + } + runner.nbctlPath, err = exec.LookPath(ovnNbctlCommand) + if err != nil { + return err + } + runner.ipPath, err = exec.LookPath(ipCommand) + if err != nil { + return err + } + return nil +} + +// Run the ovn-ctl command and retry if "Connection refused" +// poll waitng for service to become available +func runOVNretry(cmdPath string, args ...string) (*bytes.Buffer, *bytes.Buffer, error) { + + retriesLeft := 200 + for { + stdout, stderr, err := run(cmdPath, args...) + if err == nil { + return stdout, stderr, err + } + + // Connection refused + // Master may not be up so keep trying + if strings.Contains(stderr.String(), "Connection refused") { + if retriesLeft == 0 { + return stdout, stderr, err + } + retriesLeft-- + time.Sleep(2 * time.Second) + } else { + // Some other problem for caller to handle + return stdout, stderr, err + } + } +} + +func run(cmdPath string, args ...string) (*bytes.Buffer, *bytes.Buffer, error) { + stdout := &bytes.Buffer{} + stderr := &bytes.Buffer{} + cmd := runner.exec.Command(cmdPath, args...) + cmd.SetStdout(stdout) + cmd.SetStderr(stderr) + logrus.Debugf("exec: %s %s", cmdPath, strings.Join(args, " ")) + err := cmd.Run() + if err != nil { + logrus.Debugf("exec: %s %s => %v", cmdPath, strings.Join(args, " "), err) + } + return stdout, stderr, err +} + +// RunOVSOfctl runs a command via ovs-ofctl. +func RunOVSOfctl(args ...string) (string, string, error) { + stdout, stderr, err := run(runner.ofctlPath, args...) + return strings.Trim(stdout.String(), "\" \n"), stderr.String(), err +} + +// RunOVSVsctl runs a command via ovs-vsctl. +func RunOVSVsctl(args ...string) (string, string, error) { + cmdArgs := []string{fmt.Sprintf("--timeout=%d", ovsCommandTimeout)} + cmdArgs = append(cmdArgs, args...) + stdout, stderr, err := run(runner.vsctlPath, cmdArgs...) + return strings.Trim(strings.TrimSpace(stdout.String()), "\""), stderr.String(), err +} + +// RunOVNNbctlUnix runs command via ovn-nbctl, with ovn-nbctl using the unix +// domain sockets to connect to the ovsdb-server backing the OVN NB database. +func RunOVNNbctlUnix(args ...string) (string, string, error) { + cmdArgs := []string{fmt.Sprintf("--timeout=%d", ovsCommandTimeout)} + cmdArgs = append(cmdArgs, args...) + stdout, stderr, err := runOVNretry(runner.nbctlPath, cmdArgs...) + return strings.Trim(strings.TrimFunc(stdout.String(), unicode.IsSpace), "\""), + stderr.String(), err +} + +// RunIP runs a command via the iproute2 "ip" utility +func RunIP(args ...string) (string, string, error) { + stdout, stderr, err := run(runner.ipPath, args...) + return strings.TrimSpace(stdout.String()), stderr.String(), err +} |