Skip to content

Commit

Permalink
Merge pull request #297 from linkernetworks/hwchiu/return-ovs-port
Browse files Browse the repository at this point in the history
[Task] Support the PodName and InterfaceName of OVSPortInfo query.
  • Loading branch information
John-Lin authored Aug 31, 2018
2 parents 8b37c4a + 230f82f commit a53be40
Show file tree
Hide file tree
Showing 13 changed files with 158 additions and 71 deletions.
8 changes: 4 additions & 4 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
- [Get Namespace](#get-namespace)
- [Delete Namespace](#delete-namespace)
- [OVS](#ovs)
- [Get PortStats](#get-portstats)
- [Get PortInfos](#get-portinfos)



Expand Down Expand Up @@ -1675,14 +1675,14 @@ In the ovs api, we should use two parameter to indicate what OVS we want to oper
2. BridgeName: the bridge name when admin create the network in the network page.
the portal can use the list network to fetch the actual bridge name of each network.

### Get PortStats
### Get PortInfos

**GET /v1/ovs/portstats/?nodeName=xxx&bridge=xxx**
**GET /v1/ovs/portinfos/?nodeName=xxx&bridge=xxx**

Example:

```
curl http://localhost:7890/v1/ovs/portstats?nodeName=vortex-dev&bridgeName=system-47f8ce
curl http://localhost:7890/v1/ovs/portinfos?nodeName=vortex-dev&bridgeName=system-47f8ce
```

Response Data:
Expand Down
28 changes: 10 additions & 18 deletions src/entity/ovs.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
package entity

// PortStatsReceive contains information regarding the number of received
// PortStatsTransmit contains information regarding the number of transmitted
// packets, bytes, etc.
type PortStatsReceive struct {
type OVSPortStats struct {
Packets uint64 `json:"packets"`
Bytes uint64 `json:"bytes"`
Dropped uint64 `json:"dropped"`
Errors uint64 `json:"errors"`
Frame uint64 `json:"-"`
Over uint64 `json:"-"`
CRC uint64 `json:"-"`
}

// PortStatsTransmit contains information regarding the number of transmitted
// packets, bytes, etc.
type PortStatsTransmit struct {
Packets uint64 `json:"packets"`
Bytes uint64 `json:"bytes"`
Dropped uint64 `json:"dropped"`
Errors uint64 `json:"errors"`
Collisions uint64 `json:"collisions"`
}
type OVSPortStat struct {
PortID uint32 `json:'portID"`
Received PortStatsReceive `json:"received"`
Transmitted PortStatsTransmit `json:"traansmitted"`
type OVSPortInfo struct {
PortID int32 `json:"portID"`
Name string `json:"name"`
PodName string `json:"podName"`
InterfaceName string `json:"interfaceName"`
MacAddress string `json:"macAddress"`
Received OVSPortStats `json:"received"`
Transmitted OVSPortStats `json:"traansmitted"`
}
4 changes: 2 additions & 2 deletions src/kubernetes/pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ func (kc *KubeCtl) GetPods(namespace string) ([]*corev1.Pod, error) {
if err != nil {
return pods, err
}
for _, p := range podsList.Items {
pods = append(pods, &p)
for i, _ := range podsList.Items {
pods = append(pods, &podsList.Items[i])
}
return pods, nil
}
Expand Down
11 changes: 2 additions & 9 deletions src/networkcontroller/network_controller.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package networkcontroller

import (
"bytes"
"encoding/binary"
"time"

pb "github.com/linkernetworks/network-controller/messages"
Expand Down Expand Up @@ -131,7 +129,7 @@ func (nc *NetworkController) DeleteOVSNetwork(bridgeName string) error {
}

// DumpOVSPorts will dump ports infromation of the target ovs
func (nc *NetworkController) DumpOVSPorts(bridgeName string) ([]entity.OVSPortStat, error) {
func (nc *NetworkController) DumpOVSPorts(bridgeName string) ([]*pb.PortInfo, error) {
data, err := nc.ClientCtl.DumpPorts(
nc.Context,
&pb.DumpPortsRequest{
Expand All @@ -141,10 +139,5 @@ func (nc *NetworkController) DumpOVSPorts(bridgeName string) ([]entity.OVSPortSt
return nil, err
}

ovsPortStats := make([]entity.OVSPortStat, len(data.Ports))
for i, p := range data.Ports {
buf := bytes.NewBuffer(p)
err = binary.Read(buf, binary.BigEndian, &ovsPortStats[i])
}
return ovsPortStats, nil
return data.Ports, nil
}
97 changes: 95 additions & 2 deletions src/ovscontroller/ovs_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import (
"github.com/linkernetworks/vortex/src/entity"
"github.com/linkernetworks/vortex/src/networkcontroller"
"github.com/linkernetworks/vortex/src/serviceprovider"
"github.com/linkernetworks/vortex/src/utils"
"gopkg.in/mgo.v2/bson"
)

func DumpPorts(sp *serviceprovider.Container, nodeName string, bridgeName string) ([]entity.OVSPortStat, error) {
func DumpPorts(sp *serviceprovider.Container, nodeName string, bridgeName string) ([]entity.OVSPortInfo, error) {
nodeIP, err := sp.KubeCtl.GetNodeInternalIP(nodeName)
if err != nil {
return nil, err
Expand All @@ -17,5 +19,96 @@ func DumpPorts(sp *serviceprovider.Container, nodeName string, bridgeName string
nodeAddr := net.JoinHostPort(nodeIP, networkcontroller.DEFAULT_CONTROLLER_PORT)
nc, err := networkcontroller.New(nodeAddr)

return nc.DumpOVSPorts(bridgeName)
//Get the information of OVS ports
retPorts, err := nc.DumpOVSPorts(bridgeName)
if err != nil {
return nil, err
}

//We need to find a mapping for veth to podName
//1. lookup the mongodb to find all deployments which bridge name is equal to bridgeName
//2. lookup all current pods which is belogs to above deployments
//3. use the pod's UID and the interfae of each entity.DeploymentNetowrk to geneate the vethxxxxxx
//4. use the vethxxx as the key to combine the podName/interfaace and the OVSPorts
session := sp.Mongo.NewSession()
defer session.Close()

//1. lookup the mongodb to find all deployments which bridge name is equal to bridgeName
//In order to the following use, use the map here and the key is the deploynent name and the value is the deployment object.
//We need to mapping the deployment.Networks with Pod's UID and the connection is the label of the Pod is vortex=deployment.name.
deployments := []entity.Deployment{}
session.FindAll(entity.DeploymentCollectionName, bson.M{"networks.bridgeName": bridgeName}, &deployments)
deployMap := map[string]*entity.Deployment{}

for _, v := range deployments {
deployMap[v.Name] = &v
}

//2. lookup all current pods which is belogs to above deployments
pods, err := sp.KubeCtl.GetPods("")
if err != nil {
return nil, err
}

//Create a local structure to combine the deploymentNetwork and PodName.
//We want to know the interface name in that Pod, so we need to keep the deploymentNetwork object.
type portData struct {
podName string
entity.DeploymentNetwork
}
interfaces := map[string]*portData{}
for _, v := range pods {
name, ok := v.Labels["vortex"]
if !ok {
continue
}
deploy, ok := deployMap[name]
if !ok {
continue
}

//3. use the pod's UID and the interfae of each entity.DeploymentNetowrk to geneate the vethxxxxxx
//for each deploymentNetwork, we get the vethname via veth+sha256(podUID + interfaceName in container)[0:8]
uid := v.ObjectMeta.UID
for _, k := range deploy.Networks {
veth := "veth" + utils.SHA256String(string(uid) + k.IfName)[0:8]
//Use the veth name as the key and the PodName/InterfaceName in the value, we will add those inforamtion
//to OVSPortInfo later.
interfaces[veth] = &portData{
v.Name,
k,
}
}
}

//4. use the vethxxx as the key to combine the podName/interfaace and the OVSPorts
ports := []entity.OVSPortInfo{}
for _, v := range retPorts {
port := entity.OVSPortInfo{
PortID: v.ID,
Name: v.Name,
MacAddress: v.MacAddr,
Received: entity.OVSPortStats{
Packets: v.Received.Packets,
Bytes: v.Received.Byte,
Dropped: v.Received.Dropped,
Errors: v.Received.Errors,
},
Transmitted: entity.OVSPortStats{
Packets: v.Transmitted.Packets,
Bytes: v.Transmitted.Byte,
Dropped: v.Transmitted.Dropped,
Errors: v.Transmitted.Errors,
},
}

if i, ok := interfaces[port.Name]; ok {
port.InterfaceName = i.IfName
port.PodName = i.podName
}
ports = append(ports, port)

}

return ports, nil
}
3 changes: 1 addition & 2 deletions src/server/handler_ovs.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/linkernetworks/vortex/src/web"
)

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

//Get the parameter
Expand All @@ -26,7 +26,6 @@ func getOVSPortStatsHandler(ctx *web.Context) {
return
}

fmt.Println(nodeName, bridgeName)
portStats, err := ovscontroller.DumpPorts(sp, nodeName, bridgeName)
if err != nil {
response.InternalServerError(req.Request, resp.ResponseWriter, err)
Expand Down
6 changes: 3 additions & 3 deletions src/server/handler_ovs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,19 @@ func TestOVSSuite(t *testing.T) {

func (suite *OVSTestSuite) TestGetOVSPortStatsFail() {
//Empty data
httpRequest, err := http.NewRequest("GET", "http://localhost:7890/v1/ovs/portstat", nil)
httpRequest, err := http.NewRequest("GET", "http://localhost:7890/v1/ovs/portinfos", nil)
suite.NoError(err)

httpWriter := httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusBadRequest, httpWriter)

httpRequest, err = http.NewRequest("GET", "http://localhost:7890/v1/ovs/portstat?nodeName=11", nil)
httpRequest, err = http.NewRequest("GET", "http://localhost:7890/v1/ovs/portinfos?nodeName=11", nil)
httpWriter = httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusBadRequest, httpWriter)

httpRequest, err = http.NewRequest("GET", "http://localhost:7890/v1/ovs/portstat?nodeName=11&&bridgeName=111", nil)
httpRequest, err = http.NewRequest("GET", "http://localhost:7890/v1/ovs/portinfos?nodeName=11&&bridgeName=111", nil)
httpWriter = httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusInternalServerError, httpWriter)
Expand Down
2 changes: 1 addition & 1 deletion src/server/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,6 @@ func newMonitoringService(sp *serviceprovider.Container) *restful.WebService {
func newOVSService(sp *serviceprovider.Container) *restful.WebService {
webService := new(restful.WebService)
webService.Path("/v1/ovs").Consumes(restful.MIME_JSON, restful.MIME_JSON).Produces(restful.MIME_JSON, restful.MIME_JSON)
webService.Route(webService.GET("/portstat").To(handler.RESTfulServiceHandler(sp, getOVSPortStatsHandler)))
webService.Route(webService.GET("/portinfos").To(handler.RESTfulServiceHandler(sp, getOVSPortInfoHandler)))
return webService
}
10 changes: 10 additions & 0 deletions tests/01-signin-signup/user.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"loginCredential":{
"username":"[email protected]",
"password":"p@ssw0rd"
},
"displayName":"John Doe",
"firstName":"John",
"lastName":"Doe",
"phoneNumber":"0911111111"
}
5 changes: 3 additions & 2 deletions tests/07-ovs/pod.info β†’ tests/07-ovs/deployment.info
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@PODNAME@",
"name": "@DEPLOYMENTNAME@",
"labels":{},
"envVars":{},
"namespace":"default",
Expand Down Expand Up @@ -42,5 +42,6 @@
"restartPolicy":"Always",
"capability": true,
"networkType": "custom",
"nodeAffinity": []
"nodeAffinity": [],
"replicas":1
}
10 changes: 5 additions & 5 deletions tests/07-ovs/init.bash
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
if [ -z "$networkName" ]; then
export name=$(date | md5sum | cut -b 1-19)
export podName="test-pod-$name"
export deploymentName="test-deploy-$name"
export networkName="test-network-$name"
export ethName="eth-$name"
export nodeName=`kubectl get nodes | grep "Ready" | awk '{print $1}'`

rm -rf networks.json pod.json
rm -rf networks.json deployment.json
cp networks.info networks.json
cp pod.info pod.json
cp deployment.info deployment.json
sed -i "s/@NODENAME@/${nodeName}/" networks.json
sed -i "s/@NETWORKNAME@/${networkName}/" networks.json
sed -i "s/@ETHNAME@/${ethName}/" networks.json
sed -i "s/@NETWORKNAME@/${networkName}/" pod.json
sed -i "s/@PODNAME@/${podName}/" pod.json
sed -i "s/@NETWORKNAME@/${networkName}/" deployment.json
sed -i "s/@DEPLOYMENTNAME@/${deploymentName}/" deployment.json
# login
export JWT_AUTH_TOKEN=$(http --check-status http://127.0.0.1:7890/v1/users/signin < credential 2>/dev/null | jq -r ".message")
fi
35 changes: 17 additions & 18 deletions tests/07-ovs/script.bats
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,41 @@ load init
[ $status = 0 ]
}

@test "Create Pod" {
http -v --check-status --auth-type=jwt 127.0.0.1:7890/v1/pods < pod.json
@test "Create Deployment" {
http -v --check-status --auth-type=jwt 127.0.0.1:7890/v1/deployments < deployment.json
[ $? = 0 ]
#Wait the Pod
#Wait the Deployment
#jsonpath="{.status.phase}"
NEXT_WAIT_TIME=0
WAIT_LIMIT=40
until kubectl get pods ${podName} -o jsonpath="{.status.phase}" | grep "Running" || [ $NEXT_WAIT_TIME -eq $WAIT_LIMIT ]; do
until kubectl get deployments ${deploymentName} -o jsonpath="{.status.readyReplicas}" | grep "1" || [ $NEXT_WAIT_TIME -eq $WAIT_LIMIT ]; do
sleep 2
kubectl get pods ${podName}
kubectl get deployments ${deploymentName}
NEXT_WAIT_TIME=$((NEXT_WAIT_TIME+ 1))
done
[ $NEXT_WAIT_TIME != $WAIT_LIMIT ]
}

@test "Check pod network interface" {
run bash -c "kubectl exec -it ${podName} ifconfig eth12 | grep 1.2.3.4"
[ $status = 0 ]
}

@test "List Pod" {
run bash -c "http --auth-type=jwt http://127.0.0.1:7890/v1/pods/ 2>/dev/null | jq -r '.[] | select(.name == \"${podName}\").name'"
[ "$output" = "${podName}" ]
@test "List Deployment" {
run bash -c "http --auth-type=jwt http://127.0.0.1:7890/v1/deployments/ 2>/dev/null | jq -r '.[] | select(.name == \"${deploymentName}\").name'"
[ "$output" = "${deploymentName}" ]
[ $status = 0 ]
}

@test "Get OVS Port Status" {
run bash -c 'http --auth-type=jwt http://127.0.0.1:7890/v1/networks/ 2>/dev/null | jq -r ".[0].bridgeName"'
localID=`http --auth-type=jwt "127.0.0.1:7890/v1/ovs/portstat?nodeName=$nodeName&bridgeName=$output" | jq -r ".[0].PortID"`
localID=`http --auth-type=jwt "127.0.0.1:7890/v1/ovs/portinfos?nodeName=$nodeName&bridgeName=$output" | jq -r ".[3].portID"`
[ $? = 0 ]
[ "$localID" = "-1" ]

podName=`http --auth-type=jwt "127.0.0.1:7890/v1/ovs/portinfos?nodeName=$nodeName&bridgeName=$output" | jq -r ".[0].podName"`
echo $podName | grep ${deploymentName}
[ $? = 0 ]
[ "$localID" = "4294967295" ]
}

@test "Delete Pod" {
run bash -c 'http --auth-type=jwt http://127.0.0.1:7890/v1/pods/ 2>/dev/null | jq -r ".[0].id"'
run http --auth-type=jwt DELETE http://127.0.0.1:7890/v1/pods/${output} 2>/dev/null
@test "Delete Deployment" {
run bash -c 'http --auth-type=jwt http://127.0.0.1:7890/v1/deployments/ 2>/dev/null | jq -r ".[0].id"'
run http --auth-type=jwt DELETE http://127.0.0.1:7890/v1/deployments/${output} 2>/dev/null
[ $status = 0 ]
}

Expand Down
10 changes: 5 additions & 5 deletions vendor/vendor.json
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,12 @@
"revisionTime": "2018-05-24T10:14:37Z"
},
{
"checksumSHA1": "XH9LEdl9APiIfGpBh5tZrmEB5Qs=",
"checksumSHA1": "QAOy7z8HT9JxBXbIhPjTjdLusVU=",
"path": "github.com/linkernetworks/network-controller/messages",
"revision": "531599e41e1a4593dde0ce4efff466b73bd36800",
"revisionTime": "2018-08-16T16:19:53Z",
"version": "=v0.4.3",
"versionExact": "v0.4.3"
"revision": "ab932c09f38fb545d892db529a99a9d9bc6e257a",
"revisionTime": "2018-08-31T03:13:05Z",
"version": "v0.4.7",
"versionExact": "v0.4.7"
},
{
"checksumSHA1": "8bkCE7r0DcTaPDbKbwaI34Bmrbw=",
Expand Down

0 comments on commit a53be40

Please sign in to comment.