Skip to content

Commit

Permalink
Add port setting options
Browse files Browse the repository at this point in the history
  • Loading branch information
yunchen committed Jun 28, 2018
1 parent 813765f commit 8b5766c
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 0 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ before_install:
- sudo apt install openvswitch-switch
- sudo ovs-vsctl add-br ovsbr0
- go get github.com/golang/lint/golint
- go get github.com/google/go-cmp/cmp
- go get honnef.co/go/tools/cmd/staticcheck
- go get -d ./...
script:
Expand Down
85 changes: 85 additions & 0 deletions ovs/vswitch.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package ovs
import (
"encoding/json"
"fmt"
"strconv"
"strings"
)

Expand Down Expand Up @@ -179,6 +180,47 @@ func (v *VSwitchGetService) Bridge(bridge string) (BridgeOptions, error) {
}, nil
}

// Port gets configuration for a port and returns the values through
// a PortOptions struct.
func (v *VSwitchGetService) Port(port string) (PortOptions, error) {
// We only support the tag, vlan_mode, trunk option at this point.
args := []string{"--format=json", "get", "port", port, "tag", "vlan_mode", "trunk"}
out, err := v.v.exec(args...)
if err != nil {
return PortOptions{}, err
}

// If the option is not exist, OVS will return "[]\n"
options := strings.Split(strings.TrimSpace(string(out)), "\n")

var tag *int
if options[0] != "[]" {
tagNum, err := strconv.Atoi(options[0])
if err != nil {
return PortOptions{}, err
}
tag = &tagNum
}

var vlanMode *string
if options[1] != "[]" {
vlanMode = &options[1]
}

var trunk []int
if options[2] != "[]" {
if err := json.Unmarshal([]byte(options[2]), &trunk); err != nil {
return PortOptions{}, err
}
}

return PortOptions{
Tag: tag,
VLANMode: vlanMode,
Trunk: trunk,
}, nil
}

// A VSwitchSetService is used in a VSwitchService to execute 'ovs-vsctl set'
// subcommands.
type VSwitchSetService struct {
Expand Down Expand Up @@ -216,6 +258,49 @@ func (o BridgeOptions) slice() []string {
return s
}

// Port sets configuration for a port using the values from a PortOptions
// struct.
func (v *VSwitchSetService) Port(port string, options PortOptions) error {
// Prepend command line arguments before expanding options slice
// and appending it
args := []string{"set", "port", port}
args = append(args, options.slice()...)

_, err := v.v.exec(args...)
return err
}

// An PortOptions struct enables configuration of a port.
type PortOptions struct {
Tag *int
VLANMode *string
Trunk []int
}

// slice creates a string slice containing any non-zero option values from the
// struct in the format expected by Open vSwitch.
func (o PortOptions) slice() []string {
var s []string

if o.Tag != nil {
s = append(s, fmt.Sprintf("tag=%s,", strconv.Itoa(*o.Tag)))
}

if o.VLANMode != nil {
s = append(s, fmt.Sprintf("vlan_mode=%s", *o.VLANMode))
}

if len(o.Trunk) > 0 {
var strTrunk string
for _, trunk := range o.Trunk {
strTrunk += fmt.Sprintf("%s,", strconv.Itoa(trunk))
}
s = append(s, fmt.Sprintf("trunk=%s", strTrunk))
}

return s
}

// Interface sets configuration for an interface using the values from an
// InterfaceOptions struct.
func (v *VSwitchSetService) Interface(ifi string, options InterfaceOptions) error {
Expand Down
96 changes: 96 additions & 0 deletions ovs/vswitch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"errors"
"fmt"
"reflect"
"strconv"
"strings"
"testing"
)
Expand Down Expand Up @@ -501,6 +502,101 @@ func TestClientVSwitchSetBridgeProtocolsOK(t *testing.T) {
}
}

func TestClientVSwitchGetPortOptionsOK(t *testing.T) {
const port = "bond0"
vlanModeStr := "trunk"
vlanMode := &vlanModeStr
trunk := []int{1, 2, 3, 4, 5}

c := testClient([]OptionFunc{Timeout(1)}, func(cmd string, args ...string) ([]byte, error) {
if want, got := "ovs-vsctl", cmd; want != got {
t.Fatalf("incorrect command:\n- want: %v\n- got: %v",
want, got)
}

wantArgs := []string{
"--timeout=1",
"--format=json",
"get",
"port",
port,
"tag",
"vlan_mode",
"trunk",
}
if want, got := wantArgs, args; !reflect.DeepEqual(want, got) {
t.Fatalf("incorrect arguments\n- want: %v\n- got: %v",
want, got)
}

// Make the return value with newline to simulate
// the ovs-vsctl output.
data := "[]\n"
data += fmt.Sprintf("%s\n", vlanModeStr)
t, err := json.Marshal(&trunk)
if err != nil {
return nil, err
}
data += fmt.Sprintf("%s\n", string(t))
return []byte(fmt.Sprintln(data)), err
})

got, err := c.VSwitch.Get.Port(port)
if err != nil {
t.Fatalf("unexpected error for Client.VSwitch.Get.Port: %v", err)
}
if got.Tag != nil {
t.Fatalf("unexpected tag for Client.VSwitch.Get.Port: %v", *got.Tag)
}
if !reflect.DeepEqual(*got.VLANMode, *vlanMode) {
t.Fatalf("unexpected vlan_mode for Client.VSwitch.Get.Port: %v", *got.VLANMode)
}
if !reflect.DeepEqual(got.Trunk, trunk) {
t.Fatalf("unexpected trunk for Client.VSwitch.Get.Port: %v", got.Trunk)
}
}

func TestClientVSwitchSetPortOptionsOK(t *testing.T) {
const port = "bond0"
vlanModeStr := "trunk"
vlanMode := &vlanModeStr
trunk := []int{1, 2, 3, 4, 5}

c := testClient([]OptionFunc{Timeout(1)}, func(cmd string, args ...string) ([]byte, error) {
if want, got := "ovs-vsctl", cmd; want != got {
t.Fatalf("incorrect command:\n- want: %v\n- got: %v",
want, got)
}

var trunkSequence string
for _, trunk := range trunk {
trunkSequence += fmt.Sprintf("%s,", strconv.Itoa(int(trunk)))
}
wantArgs := []string{
"--timeout=1",
"set",
"port",
port,
fmt.Sprintf("vlan_mode=%s", *vlanMode),
fmt.Sprintf("trunk=%s", trunkSequence),
}
if want, got := wantArgs, args; !reflect.DeepEqual(want, got) {
t.Fatalf("incorrect arguments\n- want: %v\n- got: %v",
want, got)
}

return nil, nil
})

err := c.VSwitch.Set.Port(port, PortOptions{
VLANMode: vlanMode,
Trunk: trunk,
})
if err != nil {
t.Fatalf("unexpected error for Client.VSwitch.Set.Bridge: %v", err)
}
}

func TestClientVSwitchSetInterfaceTypeOK(t *testing.T) {
ifi := "bond0"
ifiType := InterfaceTypePatch
Expand Down

0 comments on commit 8b5766c

Please sign in to comment.