Skip to content

Commit

Permalink
Merge pull request #9 from nikhildl12/lb-patch
Browse files Browse the repository at this point in the history
Support Ovn Load Balancer operations
  • Loading branch information
hzhou8 authored Mar 12, 2019
2 parents 46928dd + de8baea commit d91fdd2
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 3 deletions.
3 changes: 2 additions & 1 deletion examples/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package main

import (
"fmt"

"os"

"github.com/ebay/go-ovn/goovn"
Expand All @@ -34,6 +33,7 @@ const (

var ovndbapi goovn.OVNDBApi


func init() {
var ovs_rundir = os.Getenv("OVS_RUNDIR")
if ovs_rundir == "" {
Expand All @@ -44,6 +44,7 @@ func init() {
}

func main() {

ocmd := ovndbapi.LSWAdd("ls1")
ovndbapi.Execute(ocmd)
ocmd = ovndbapi.LSPAdd("ls1", "test")
Expand Down
18 changes: 18 additions & 0 deletions goovn/apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ type OVNDBApi interface {
ASAdd(name string, addrs []string, external_ids map[string]string) *OvnCommand
// Delete addressset
ASDel(name string) *OvnCommand
// Add LB
LBAdd(name string, vipPort string, protocol string, addrs []string) *OvnCommand
// Delete LB with given name
LBDel(name string) *OvnCommand
// Update existing LB
LBUpdate(name string, vipPort string, protocol string, addrs []string) *OvnCommand

// Set options in lswtich
LSSetOpt(lsp string, options map[string]string) *OvnCommand
// Exec command, support mul-commands in one transaction.
Expand All @@ -71,6 +78,8 @@ type OVNDBApi interface {

GetAddressSets() []*AddressSet
GetASByName(name string) *AddressSet
// Get LB with given name
GetLB(name string) []*LoadBalancer

SetCallBack(callback OVNSignal)
}
Expand Down Expand Up @@ -109,6 +118,15 @@ type LogicalSwitch struct {
ExternalID map[interface{}]interface{}
}

type LoadBalancer struct {
UUID string
Name string
vips map[interface{}]interface{}
protocol string
ExternalID map[interface{}]interface{}
}


type LogcalPort struct {
UUID string
Name string
Expand Down
2 changes: 1 addition & 1 deletion goovn/ovndb.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const (
LSWITCH string = "Logical_Switch"
LPORT string = "Logical_Switch_Port"
ACLS string = "ACL"
LB string = "Load_Balancer"
Address_Set string = "Address_Set"
)

Expand Down Expand Up @@ -88,7 +89,6 @@ func GetInstance(socketfile string, protocol string, server string, port int, ca
} else {
err = errors.New(fmt.Sprintf("The protocol [%s] is not supported", protocol))
}

if err != nil {
panic(fmt.Sprint("Library goovn initilizing failed", err))
os.Exit(1)
Expand Down
22 changes: 21 additions & 1 deletion goovn/ovnnb.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func newNBBySocket(socketfile string, callback OVNSignal) (*OVNDB, error) {

func newNBByServer(server string, port int, callback OVNSignal) (*OVNDB, error) {
odb, err := newNBClient("", TCP, server, port)
if err != nil {
if err == nil {
return &OVNDB{newNBImp(odb, callback)}, nil
} else {
return nil, err
Expand All @@ -91,6 +91,20 @@ func (odb *OVNDB) LSPDel(lsp string) *OvnCommand {
return odb.imp.lspDelImp(lsp)
}



func (odb *OVNDB) LBAdd(name string, vipPort string, protocol string, addrs []string) *OvnCommand {
return odb.imp.lbAddImpl(name, vipPort, protocol, addrs)
}

func (odb *OVNDB) LBUpdate(name string, vipPort string, protocol string, addrs []string) *OvnCommand {
return odb.imp.lbUpdateImpl(name, vipPort, protocol, addrs)
}

func (odb *OVNDB) LBDel(name string) *OvnCommand {
return odb.imp.lbDelImp(name)
}

func (odb *OVNDB) LSPSetAddress(lsp string, addresses ...string) *OvnCommand {
return odb.imp.lspSetAddressImp(lsp, addresses...)
}
Expand Down Expand Up @@ -139,6 +153,7 @@ func (odb *OVNDB) GetACLsBySwitch(lsw string) []*ACL {
return odb.imp.GetACLsBySwitch(lsw)
}


func (odb *OVNDB) GetAddressSets() []*AddressSet {
return odb.imp.GetAddressSets()
}
Expand All @@ -147,6 +162,11 @@ func (odb *OVNDB) GetASByName(name string) *AddressSet {
return odb.imp.GetASByName(name)
}

func (odb *OVNDB) GetLB(name string) []*LoadBalancer {
return odb.imp.GetLB(name)
}


func (odb *OVNDB) SetCallBack(callback OVNSignal) {
odb.imp.callback = callback
}
115 changes: 115 additions & 0 deletions goovn/ovnnbimp.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,96 @@ func (odbi *ovnDBImp) lswListImp() *OvnCommand {
return &OvnCommand{operations, odbi, make([][]map[string]interface{}, len(operations))}
}


func (odbi *ovnDBImp) lbUpdateImpl(name string, vipPort string, protocol string, addrs []string) *OvnCommand {

//row to update
lb := make(OVNRow)

// prepare vips map
vipMap := make(map[string]string)
members := strings.Join(addrs, ",")
vipMap[vipPort] = members

oMap, err := libovsdb.NewOvsMap(vipMap)
if err != nil {
glog.Fatalf("Update LB:%v vip map is not correct: %v", name, err)
return nil
}
lb["vips"] = oMap
lb["protocol"] = protocol

condition := libovsdb.NewCondition("name", "==", name)

insertOp := libovsdb.Operation{
Op: update,
Table: LB,
Row: lb,
Where: []interface{}{condition},
}
operations := []libovsdb.Operation{insertOp}
return &OvnCommand{operations, odbi, make([][]map[string]interface{}, len(operations))}
}


func (odbi *ovnDBImp) lbAddImpl(name string, vipPort string, protocol string, addrs []string) *OvnCommand {
namedUUID := "lb_add" + strconv.Itoa(rand.Int())
//row to insert
lb := make(OVNRow)
lb["name"] = name

if odbi.getRowUUID(LB, lb) != "" {
glog.V(OVNLOGLEVEL).Info("The load balancer existed, and will get nil command")
return nil
}
// prepare vips map
vipMap := make(map[string]string)
members := strings.Join(addrs, ",")
vipMap[vipPort] = members

oMap, err := libovsdb.NewOvsMap(vipMap)
if err != nil {
glog.Fatalf("Add LB: vip map is not correct")
return nil
}
lb["vips"] = oMap
lb["protocol"] = protocol

insertOp := libovsdb.Operation{
Op: insert,
Table: LB,
Row: lb,
UUIDName: namedUUID,
}

mutateUUID := []libovsdb.UUID{{namedUUID}}
mutateSet, _ := libovsdb.NewOvsSet(mutateUUID)
mutation := libovsdb.NewMutation("load_balancer", insert, mutateSet)
// TODO: Add filter for LS name
condition := libovsdb.NewCondition("name", "!=", "")

mutateOp := libovsdb.Operation{
Op: mutate,
Table: LSWITCH,
Mutations: []interface{}{mutation},
Where: []interface{}{condition},
}
operations := []libovsdb.Operation{insertOp, mutateOp}
return &OvnCommand{operations, odbi, make([][]map[string]interface{}, len(operations))}
}

func (odbi *ovnDBImp) lbDelImp(name string) *OvnCommand {
condition := libovsdb.NewCondition("name", "==", name)
delOp := libovsdb.Operation{
Op: del,
Table: LB,
Where: []interface{}{condition},
}
operations := []libovsdb.Operation{delOp}
return &OvnCommand{operations, odbi, make([][]map[string]interface{}, len(operations))}
}


func (odbi *ovnDBImp) lswAddImp(lsw string) *OvnCommand {
namedUUID := "lsw_add" + strconv.Itoa(rand.Int())
//row to insert
Expand Down Expand Up @@ -703,6 +793,31 @@ func (odbi *ovnDBImp) GetLogicPortsBySwitch(lsw string) []*LogcalPort {
return lplist
}

func (odbi *ovnDBImp) GetLB(name string) []*LoadBalancer {
var lbList []*LoadBalancer
odbi.cachemutex.Lock()
defer odbi.cachemutex.Unlock()

for uuid, drows := range odbi.cache[LB] {
if lbName, ok := drows.Fields["name"].(string); ok && lbName == name {
lb := odbi.RowToLB(uuid)
lbList = append(lbList, lb)
}
}
return lbList
}

func (odbi *ovnDBImp) RowToLB(uuid string) *LoadBalancer {
return &LoadBalancer{
UUID: uuid,
protocol: odbi.cache[LB][uuid].Fields["protocol"].(string),
Name: odbi.cache[LB][uuid].Fields["name"].(string),
vips: odbi.cache[LB][uuid].Fields["vips"].(libovsdb.OvsMap).GoMap,
ExternalID: odbi.cache[LB][uuid].Fields["external_ids"].(libovsdb.OvsMap).GoMap,
}
}


func (odbi *ovnDBImp) RowToACL(uuid string) *ACL {
acl := &ACL{
UUID: uuid,
Expand Down
40 changes: 40 additions & 0 deletions goovn/ovnnbimp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,43 @@ func TestAddressSet(t *testing.T) {
ovndbapi.Execute(c...)
assert.Equal(t, false, findAS("AS2"), "test AS remove")
}


func TestLoadBalancer(t *testing.T){
t.Logf("Adding LB to OVN")
ocmd := ovndbapi.LBAdd("lb1", "192.168.0.19:80", "tcp", []string{"10.0.0.11:80","10.0.0.12:80"})
err := ovndbapi.Execute(ocmd)
if err != nil {
t.Fatalf("Adding LB OVN failed with err %v", err)
}
t.Logf("Adding LB to OVN Done")

t.Logf("Updating LB to OVN")
ocmd = ovndbapi.LBUpdate("lb1", "192.168.0.10:80", "tcp", []string{"10.10.10.127:8080","10.10.10.120:8080"})
err = ovndbapi.Execute(ocmd)
if err != nil {
t.Fatalf("Updating LB OVN failed with err %v", err)
}
t.Logf("Updating LB to OVN done")

t.Logf("Gettting LB by name")
lb := ovndbapi.GetLB("lb1")
if len(lb) != 1 {
t.Fatalf("err getting lbs, total:%v", len(lb))
}
t.Logf("Lb found:%+v", lb[0])

t.Logf("Deleting LB")
ocmd = ovndbapi.LBDel("lb1")
err = ovndbapi.Execute(ocmd)
if err != nil {
t.Fatalf("err executing command:%v", err)
}

// Verify deletion
lb = ovndbapi.GetLB("lb1")
if len(lb) != 0 {
t.Fatalf("error: lb deletion not done, total:%v", len(lb))
}
t.Logf("LB deletion done")
}

0 comments on commit d91fdd2

Please sign in to comment.