Skip to content

Commit

Permalink
network: Implement of getting OVS/OVN information
Browse files Browse the repository at this point in the history
  • Loading branch information
ish-hcc committed Dec 6, 2023
1 parent 4be0388 commit bff37c9
Show file tree
Hide file tree
Showing 7 changed files with 406 additions and 3 deletions.
8 changes: 8 additions & 0 deletions driver/infra/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,13 @@ func GetNetworkInfo() (modelNet.Network, error) {
return n, errors.New(errMsg)
}

n.VirtualNetwork.OVS, err = network.GetOVSInfo()
if err != nil {
errMsg := "OVS: " + err.Error()
logger.Println(logger.DEBUG, true, errMsg)

return n, errors.New(errMsg)
}

return n, nil
}
230 changes: 230 additions & 0 deletions driver/network/ovs_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
// Getting ovs bridges for Linux

//go:build linux

package network

import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/cloud-barista/cm-honeybee/model/network"
"github.com/jollaman999/utils/fileutil"
"github.com/jollaman999/utils/logger"
"regexp"
"time"

"github.com/digitalocean/go-openvswitch/ovsdb"
libovsdb "github.com/ovn-org/libovsdb/ovsdb"
)

func ovsSliceToGoNotation(val interface{}) (interface{}, error) {
switch sl := val.(type) {
case []interface{}:
bsliced, err := json.Marshal(sl)
if err != nil {
return nil, err
}
switch sl[0] {
case "uuid", "named-uuid":
var uuid libovsdb.UUID
err = json.Unmarshal(bsliced, &uuid)
return ovsUUID{UUID: uuid.GoUUID}, err
case "set":
var oSet libovsdb.OvsSet
err = json.Unmarshal(bsliced, &oSet)
return ovsSet{Set: oSet.GoSet}, err
case "map":
var oMap libovsdb.OvsMap
err = json.Unmarshal(bsliced, &oMap)
return ovsMap{Map: oMap.GoMap}, err
}
return val, nil
}
return val, nil
}

func cleanInner(val []interface{}) ([]interface{}, error) {
var newVal []interface{}

for _, s := range val {
var v []interface{}
bs, err := json.Marshal(s)
if err != nil {
return nil, err
}
err = json.Unmarshal(bs, &v)
if err != nil {
return nil, err
}
cleaned, err := ovsSliceToGoNotation(v)
if err != nil {
return nil, err
}
newVal = append(newVal, cleaned)
}

return newVal, nil
}

var validUUID = regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)

type ovsUUID struct {
UUID string
}

func (u ovsUUID) validateUUID() error {
if len(u.UUID) != 36 {
return fmt.Errorf("uuid exceeds 36 characters")
}

if !validUUID.MatchString(u.UUID) {
return fmt.Errorf("uuid does not match regexp")
}

return nil
}

func (u ovsUUID) MarshalJSON() ([]byte, error) {
return json.Marshal(u.UUID)
}

type ovsSet struct {
Set []interface{}
}

func (o ovsSet) MarshalJSON() ([]byte, error) {
newVal, err := cleanInner(o.Set)
if err != nil {
return nil, err
}

return json.Marshal(newVal)
}

type ovsMap struct {
Map map[interface{}]interface{}
}

func (o ovsMap) MarshalJSON() ([]byte, error) {
if len(o.Map) > 0 {
var innerMap []interface{}
for key, val := range o.Map {
var mapSeg []interface{}
mapSeg = append(mapSeg, key)
mapSeg = append(mapSeg, val)
innerMap = append(innerMap, mapSeg)
}
newVal, err := cleanInner(innerMap)
if err != nil {
return nil, err
}
return json.Marshal(newVal)
}
return []byte("[]"), nil
}

var ovsDBSocketFile = "/var/run/openvswitch/db.sock"

func GetOVSInfo() ([]network.OVSBridge, error) {
var ovsBridges []network.OVSBridge

if !fileutil.IsExist(ovsDBSocketFile) {
logger.Println(logger.DEBUG, true, "OVS: OVS database socket file not found.")

return ovsBridges, nil
}

c, err := ovsdb.Dial("unix", "/var/run/openvswitch/db.sock")
if err != nil {
errMsg := fmt.Sprintf("failed to dial: %v", err)
logger.Println(logger.ERROR, true, "OVS: "+errMsg)

return ovsBridges, errors.New(errMsg)
}
defer func() {
_ = c.Close()
}()

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

dbs, err := c.ListDatabases(ctx)
if err != nil {
errMsg := fmt.Sprintf("failed to list databases: %v", err)
logger.Println(logger.ERROR, true, "OVS: "+errMsg)

return ovsBridges, errors.New(errMsg)
}

var databaseFound = false
var db string
for _, db = range dbs {
if db == "Open_vSwitch" {
databaseFound = true
break
}
}

if !databaseFound {
errMsg := "Open_vSwitch database not found"
logger.Println(logger.ERROR, true, "OVS: "+errMsg)

return ovsBridges, errors.New(errMsg)
}

rows, err := c.Transact(ctx, db, []ovsdb.TransactOp{
ovsdb.Select{
Table: "Bridge",
},
})
if err != nil {
errMsg := fmt.Sprintf("failed to perform transaction: %v", err)
logger.Println(logger.ERROR, true, "OVS: "+errMsg)

return ovsBridges, errors.New(errMsg)
}

type bridge map[string]interface{}

var bridges []bridge

for _, row := range rows {
b := make(bridge)

for key, val := range row {
if key == "_uuid" {
key = "uuid"
} else if key == "_version" {
key = "version"
}

val, err = ovsSliceToGoNotation(val)
if err != nil {
logger.Println(logger.ERROR, true, "OVS: "+err.Error())

return ovsBridges, err
}

b[key] = val
}
bridges = append(bridges, b)
}

jsonBytes, err := json.Marshal(bridges)
if err != nil {
logger.Println(logger.ERROR, true, "OVS: "+err.Error())

return ovsBridges, err
}

err = json.Unmarshal(jsonBytes, &ovsBridges)
if err != nil {
logger.Println(logger.ERROR, true, "OVS: "+err.Error())

return ovsBridges, err
}

return ovsBridges, nil
}
19 changes: 19 additions & 0 deletions driver/network/ovs_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Getting ovs bridges is not implemented for Windows

//go:build windows

package network

import (
"github.com/cloud-barista/cm-honeybee/model/network"
"github.com/jollaman999/utils/logger"
)

func GetOVSInfo() ([]network.OVSBridge, error) {
var ovsBridges []network.OVSBridge

logger.Println(logger.INFO, false,
"OVS: Getting OVS information is not implemented for Windows.")

return ovsBridges, nil
}
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ require (
gopkg.in/yaml.v3 v3.0.1
)

require github.com/coreos/go-iptables v0.7.0
require (
github.com/coreos/go-iptables v0.7.0
github.com/digitalocean/go-openvswitch v0.0.0-20230210190010-977d98586f70
github.com/ovn-org/libovsdb v0.6.0
)

require (
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
Expand Down
Loading

0 comments on commit bff37c9

Please sign in to comment.