Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add network controller #30

Merged
merged 11 commits into from
Jun 26, 2018
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ notifications:

before_install:
- go get -u github.com/kardianos/govendor
- sudo apt-get install -y git build-essential openvswitch-switch
- docker run -d -v /run/openvswitch/db.sock:/var/run/openvswitch/db.sock -p 50051:50051 sdnvortex/network-controller:v0.1.1 /go/bin/server -tcp=0.0.0.0:50051

install:
- make pre-build

script:
- make build
- make test
- make src.test-coverage
- sudo -E PATH=$PATH TEST_GRPC=1 make src.test-coverage
- docker build --tag sdnvortex/vortex --file ./dockerfiles/Dockerfile .

before_deploy:
Expand Down
4 changes: 1 addition & 3 deletions src/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/linkernetworks/logger"
"github.com/linkernetworks/mongo"
"github.com/linkernetworks/redis"
"k8s.io/client-go/rest"
)

type Config struct {
Expand All @@ -18,8 +17,6 @@ type Config struct {

// the version settings of the current application
Version string `json:"version"`

Kubernetes *rest.Config `json:"kubernetes"`
}

func Read(path string) (c Config, err error) {
Expand All @@ -32,6 +29,7 @@ func Read(path string) (c Config, err error) {
if err := decoder.Decode(&c); err != nil {
return c, fmt.Errorf("Failed to load the config file: %v\n", err)
}

return c, nil
}

Expand Down
65 changes: 65 additions & 0 deletions src/networkcontroller/network_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package networkcontroller

import (
"time"

pb "github.com/linkernetworks/network-controller/messages"
"github.com/linkernetworks/vortex/src/entity"
"github.com/linkernetworks/vortex/src/kubernetes"
"golang.org/x/net/context"
"google.golang.org/grpc"
)

type NetworkController struct {
KubeCtl *kubernetes.KubeCtl
ClientCtl pb.NetworkControlClient
Network entity.Network
Context context.Context
}

func New(kubeCtl *kubernetes.KubeCtl, network entity.Network) (*NetworkController, error) {
nodeIP, err := kubeCtl.GetNodeExternalIP(network.NodeName)
if err != nil {
return nil, err
}

// Set up a connection to the server.
conn, err := grpc.Dial(nodeIP+":50051", grpc.WithInsecure())
if err != nil {
return nil, err
}

ctx, _ := context.WithTimeout(context.Background(), time.Second)

return &NetworkController{
KubeCtl: kubeCtl,
ClientCtl: pb.NewNetworkControlClient(conn),
Network: network,
Context: ctx,
}, nil
}

func (nc *NetworkController) CreateNetwork() error {
_, err := nc.ClientCtl.CreateBridge(
nc.Context,
&pb.CreateBridgeRequest{
BridgeName: nc.Network.BridgeName,
})
if err != nil {
return err
}

for _, port := range nc.Network.PhysicalPorts {
_, err := nc.ClientCtl.AddPort(
nc.Context,
&pb.AddPortRequest{
BridgeName: nc.Network.BridgeName,
IfaceName: port.Name,
})
if err != nil {
return err
}
}

return nil
}
109 changes: 109 additions & 0 deletions src/networkcontroller/network_controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package networkcontroller

import (
"fmt"
"github.com/linkernetworks/vortex/src/entity"
"github.com/linkernetworks/vortex/src/kubernetes"
"github.com/moby/moby/pkg/namesgenerator"
"github.com/stretchr/testify/suite"
"math/rand"
"os"
"os/exec"
"runtime"
"testing"
"time"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fakeclientset "k8s.io/client-go/kubernetes/fake"
)

func init() {
rand.Seed(time.Now().UnixNano())
}

type NetworkControllerTestSuite struct {
suite.Suite
kubectl *kubernetes.KubeCtl
ifName string
nodeName string
}

func (suite *NetworkControllerTestSuite) SetupSuite() {
// init fakeclient
fakeclient := fakeclientset.NewSimpleClientset()
namespace := "default"
suite.kubectl = kubernetes.New(fakeclient, namespace)

//Create a fake clinet
//Init
nodeAddr := corev1.NodeAddress{
Type: "ExternalIP",
Address: "127.0.0.1",
}

suite.nodeName = namesgenerator.GetRandomName(0)[0:8]
node := corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: suite.nodeName,
},
Status: corev1.NodeStatus{
Addresses: []corev1.NodeAddress{nodeAddr},
},
}
_, err := suite.kubectl.Clientset.CoreV1().Nodes().Create(&node)
suite.NoError(err)

//There's a length limit of link name
suite.ifName = namesgenerator.GetRandomName(0)[0:8]
pName := namesgenerator.GetRandomName(0)[0:8]
//Create a veth for testing
err = exec.Command("ip", "link", "add", suite.ifName, "type", "veth", "peer", "name", pName).Run()
suite.NoError(err)
}

func TestNetworkControllerSuite(t *testing.T) {
if runtime.GOOS != "linux" {
fmt.Println("We only testing the ovs function on Linux Host")
t.Skip()
return
}
if _, defined := os.LookupEnv("TEST_GRPC"); !defined {
t.SkipNow()
return
}
suite.Run(t, new(NetworkControllerTestSuite))
}

func (suite *NetworkControllerTestSuite) TestNewNetworkController() {
network := entity.Network{
NodeName: suite.nodeName,
}

_, err := New(suite.kubectl, network)
suite.NoError(err)
}

func (suite *NetworkControllerTestSuite) TestCreateNetwork() {
//Parameters
eth1 := entity.PhysicalPort{
Name: suite.ifName,
MTU: 1500,
VlanTags: []int{2043, 2143, 2243},
}

tName := namesgenerator.GetRandomName(0)
network := entity.Network{
BridgeName: tName,
BridgeType: "ovs",
NodeName: suite.nodeName,
PhysicalPorts: []entity.PhysicalPort{eth1},
}

nc, err := New(suite.kubectl, network)
suite.NoError(err)
err = nc.CreateNetwork()
suite.NoError(err)

defer exec.Command("ovs-vsctl", "del-br", tName).Run()
}
18 changes: 16 additions & 2 deletions src/server/handler_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import (
"github.com/linkernetworks/vortex/src/entity"
response "github.com/linkernetworks/vortex/src/net/http"
"github.com/linkernetworks/vortex/src/net/http/query"
"github.com/linkernetworks/vortex/src/networkcontroller"
"github.com/linkernetworks/vortex/src/web"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)

func createNetworkHandler(ctx *web.Context) {
as, req, resp := ctx.ServiceProvider, ctx.Request, ctx.Response
sp, req, resp := ctx.ServiceProvider, ctx.Request, ctx.Response

network := entity.Network{}
if err := req.ReadEntity(&network); err != nil {
Expand All @@ -25,7 +26,7 @@ func createNetworkHandler(ctx *web.Context) {
return
}

session := as.Mongo.NewSession()
session := sp.Mongo.NewSession()
defer session.Close()
session.C(entity.NetworkCollectionName).EnsureIndex(mgo.Index{
Key: []string{"bridgeName", "nodeName"},
Expand All @@ -42,6 +43,19 @@ func createNetworkHandler(ctx *web.Context) {
}
}

nc, err := networkcontroller.New(sp.KubeCtl, network)
if err != nil {
logger.Errorf("Failed to new network controller: %s", err.Error())
response.InternalServerError(req.Request, resp.ResponseWriter, err)
return
}

if err := nc.CreateNetwork(); err != nil {
logger.Errorf("Failed to create network: %s", err.Error())
response.InternalServerError(req.Request, resp.ResponseWriter, err)
return
}

network.ID = bson.NewObjectId()
network.CreatedAt = timeutils.Now()
if err := session.Insert(entity.NetworkCollectionName, &network); err != nil {
Expand Down
Loading