diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..255ce6ee --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,25 @@ +name: test + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: int_test + run: | + sudo modprobe openvswitch && \ + sudo modprobe 8021q && \ + export DEBIAN_FRONTEND=noninteractive && \ + echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections + sudo apt-get update && \ + sudo apt-get remove docker docker-engine docker.io containerd runc python3-yaml && \ + sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common && \ + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \ + sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \ + sudo apt-get update && sudo apt-get install docker-ce docker-ce-cli containerd.io && \ + sudo pip3 install -U pip && \ + sudo pip3 install -U setuptools && \ + sudo pip3 install -U faucet && \ + ./test_dovesnap.sh diff --git a/ovs/driver.go b/ovs/driver.go index d2366cef..d4df0c63 100755 --- a/ovs/driver.go +++ b/ovs/driver.go @@ -20,6 +20,8 @@ const ( bridgePrefix = "ovsbr-" containerEthName = "eth" + bridgeAddPorts = "ovs.bridge.add_ports" + bridgeDpid = "ovs.bridge.dpid" bridgeController = "ovs.bridge.controller" @@ -113,6 +115,11 @@ func (d *Driver) CreateNetwork(r *networkplugin.CreateNetworkRequest) error { return err } + add_ports, err := getBridgeAddPorts(r) + if err != nil { + return err + } + ns := &NetworkState{ BridgeName: bridgeName, MTU: mtu, @@ -124,7 +131,7 @@ func (d *Driver) CreateNetwork(r *networkplugin.CreateNetworkRequest) error { d.networks[r.NetworkID] = ns log.Debugf("Initializing bridge for network %s", r.NetworkID) - if err := d.initBridge(r.NetworkID, controller, dpid); err != nil { + if err := d.initBridge(r.NetworkID, controller, dpid, add_ports); err != nil { delete(d.networks, r.NetworkID) return err } @@ -373,6 +380,10 @@ func getBridgeDpid(r *networkplugin.CreateNetworkRequest) (string, error) { return getGenericOption(r, bridgeDpid), nil } +func getBridgeAddPorts(r *networkplugin.CreateNetworkRequest) (string, error) { + return getGenericOption(r, bridgeAddPorts), nil +} + func getGatewayIP(r *networkplugin.CreateNetworkRequest) (string, string, error) { // FIXME: Dear future self, I'm sorry for leaving you with this mess, but I want to get this working ASAP // This should be an array diff --git a/ovs/ovs_bridge.go b/ovs/ovs_bridge.go index 1a8bf8a1..1c5230d9 100644 --- a/ovs/ovs_bridge.go +++ b/ovs/ovs_bridge.go @@ -2,6 +2,7 @@ package ovs import ( "fmt" + "strings" log "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/iptables" @@ -18,25 +19,44 @@ func (ovsdber *ovsdber) deleteBridge(bridgeName string) error { } // setupBridge If bridge does not exist create it. -func (d *Driver) initBridge(id string, controller string, dpid string) error { +func (d *Driver) initBridge(id string, controller string, dpid string, add_ports string) error { bridgeName := d.networks[id].BridgeName if err := d.ovsdber.addBridge(bridgeName); err != nil { log.Errorf("error creating ovs bridge [ %s ] : [ %s ]", bridgeName, err) return err } + var ovsConfigCmds [][]string if dpid != "" { - err := VsCtl("set", "bridge", bridgeName, fmt.Sprintf("other-config:datapath-id=%s", dpid)) - if err != nil { - return err - } + ovsConfigCmds = append(ovsConfigCmds, []string{"set", "bridge", bridgeName, fmt.Sprintf("other-config:datapath-id=%s", dpid)}) } if controller != "" { - err := VsCtl("set-controller", bridgeName, controller) + ovsConfigCmds = append(ovsConfigCmds, []string{"set", "bridge", bridgeName, "fail-mode=secure"}) + controllers := append([]string{"set-controller", bridgeName}, strings.Split(controller, ",")...) + ovsConfigCmds = append(ovsConfigCmds, controllers) + } + + if add_ports != "" { + for _, add_port_number_str := range strings.Split(add_ports, ",") { + add_port_number := strings.Split(add_port_number_str, "/") + add_port := add_port_number[0] + if len(add_port_number) == 2 { + number := add_port_number[1] + ovsConfigCmds = append(ovsConfigCmds, []string{"add-port", bridgeName, add_port, "--", "set", "Interface", add_port, fmt.Sprintf("ofport_request=%s", number)}) + } else { + ovsConfigCmds = append(ovsConfigCmds, []string{"add-port", bridgeName, add_port}) + } + } + } + + for _, cmd := range ovsConfigCmds { + err := VsCtl(cmd...) if err != nil { - return err - } + // At least one bridge config failed, so delete the bridge. + VsCtl("del-br", bridgeName) + return err + } } bridgeMode := d.networks[id].Mode diff --git a/test_dovesnap.sh b/test_dovesnap.sh new file mode 100755 index 00000000..df2aa48d --- /dev/null +++ b/test_dovesnap.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +export TMPDIR=/tmp +export FAUCET_CONFIG=$TMPDIR/faucet.yaml +export FAUCET_LOG=$TMPDIR/faucet.log +export FAUCET_EXCEPTION_LOG=$TMPDIR/faucet_exception.log + +cat >$FAUCET_CONFIG <