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

[Task] Support the PodName and InterfaceName of OVSPortInfo query. #297

Merged
merged 7 commits into from
Aug 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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