Skip to content

Commit 76ea572

Browse files
fgschwanlebauce
authored andcommitted
test: added functional tests for topology probe of VPP running in docker container
Signed-off-by: Filip Gschwandtner <filip.gschwandtner@pantheon.tech>
1 parent a10385d commit 76ea572

File tree

2 files changed

+126
-2
lines changed

2 files changed

+126
-2
lines changed

scripts/ci/jobs/jobs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@
374374
builders:
375375
- skydive-cleanup
376376
- skydive-test:
377-
test: BACKEND=elasticsearch ARGS="-ovs.oflow.native" scripts/ci/run-functional-tests.sh
377+
test: BACKEND=elasticsearch WITH_DOCKER_VPP=true ARGS="-ovs.oflow.native" scripts/ci/run-functional-tests.sh
378378
publishers:
379379
- junit:
380380
results: tests.xml
@@ -392,7 +392,7 @@
392392
builders:
393393
- skydive-cleanup
394394
- skydive-test:
395-
test: BACKEND=orientdb scripts/ci/run-functional-tests.sh
395+
test: BACKEND=orientdb WITH_DOCKER_VPP=true scripts/ci/run-functional-tests.sh
396396
publishers:
397397
- junit:
398398
results: tests.xml

tests/vpp_test.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
/*
44
* Copyright (C) 2019 Red Hat, Inc.
5+
* Copyright (c) 2019 PANTHEON.tech s.r.o.
56
*
67
* Licensed under the Apache License, Version 2.0 (the "License");
78
* you may not use this file except in compliance with the License.
@@ -27,9 +28,15 @@ import (
2728
"time"
2829

2930
"github.com/skydive-project/skydive/graffiti/graph"
31+
"github.com/skydive-project/skydive/gremlin"
3032
"github.com/skydive-project/skydive/topology/probes/vpp"
3133
)
3234

35+
const (
36+
dockerImageWithRunningVPP = "ligato/vpp-base:19.04"
37+
vppWaitScript = "sh -c 'retry=%d;until docker exec %s vppctl sh version || [ $retry -eq 0 ]; do retry=$(( retry-1 ));sleep 0.5s;echo \"VPP not ready-retries left \"$retry;done'"
38+
)
39+
3340
func createLoopback(t *testing.T) string {
3441
cmd := "vppctl loopback create-interface"
3542
out, err := exec.Command("/bin/sh", "-c", cmd).CombinedOutput()
@@ -99,3 +106,120 @@ func TestVPPLoopback(t *testing.T) {
99106
}
100107
RunTest(t, test)
101108
}
109+
110+
func TestVPPInDocker(t *testing.T) {
111+
test := &Test{
112+
setupCmds: []Cmd{
113+
{fmt.Sprintf("docker run -d -t -i --privileged --name test-skydive-docker-running-vpp %s", dockerImageWithRunningVPP), false},
114+
{fmt.Sprintf(vppWaitScript, 30, "test-skydive-docker-running-vpp"), true},
115+
},
116+
117+
tearDownCmds: []Cmd{
118+
{"docker rm -f test-skydive-docker-running-vpp", false},
119+
},
120+
121+
mode: Replay,
122+
123+
checks: []CheckFunction{func(c *CheckContext) error {
124+
return assertOneEndNode(c, c.gremlin.V().Has("Type", "netns").
125+
Out("Type", "vpp"))
126+
}},
127+
}
128+
129+
RunTest(t, test)
130+
}
131+
132+
func TestVPPConnectingToVeth(t *testing.T) {
133+
test := &Test{
134+
setupCmds: []Cmd{
135+
{fmt.Sprintf("docker run -d -t -i --privileged --name test-skydive-docker-vpp-to-veth %s", dockerImageWithRunningVPP), false},
136+
{fmt.Sprintf(vppWaitScript, 30, "test-skydive-docker-vpp-to-veth"), true},
137+
{"docker exec test-skydive-docker-vpp-to-veth ip link add name veth-container type veth peer name veth-host", true}, // creating veth tunnel (that can be used to tunnel docker container and docker host)
138+
{"docker exec test-skydive-docker-vpp-to-veth ip link set dev veth-container up", true},
139+
{"docker exec test-skydive-docker-vpp-to-veth ip link set dev veth-host up", true}, // no need for this test to actually push veth-host to network namespace of docker host OS
140+
{"docker exec test-skydive-docker-vpp-to-veth vppctl create host-interface name veth-container", true}, // grabbing and using veth-container end of tunnel in VPP
141+
{"docker exec test-skydive-docker-vpp-to-veth vppctl set int state host-veth-container up", true},
142+
},
143+
144+
tearDownCmds: []Cmd{
145+
{"docker rm -f test-skydive-docker-vpp-to-veth", false},
146+
},
147+
148+
mode: Replay,
149+
150+
checks: []CheckFunction{func(c *CheckContext) error {
151+
return assertOneEndNode(c, c.gremlin.V().Has("Type", "interface", "Driver", "vpp", "Name", "host-veth-container").
152+
In("Type", "veth", "Name", "veth-container"))
153+
}},
154+
}
155+
156+
RunTest(t, test)
157+
}
158+
159+
func TestVPPMemifTunnel(t *testing.T) {
160+
vpp1Container := "test-skydive-docker-vpp1-with-memif-tunnel"
161+
vpp2Container := "test-skydive-docker-vpp2-with-memif-tunnel"
162+
test := &Test{
163+
setupCmds: []Cmd{
164+
// prepare container-shared folder (docker would create it automatically, but creating it now and with user that is running test resolves permission problems in teardown)
165+
{"mkdir /tmp/skydivetests-dockervpp-sockets", false},
166+
167+
// starting docker contrainers
168+
{fmt.Sprintf("docker run -d -t -i -v /tmp/skydivetests-dockervpp-sockets/:/run/othersockets/ --privileged --name %s %s", vpp1Container, dockerImageWithRunningVPP), false},
169+
{fmt.Sprintf("docker run -d -t -i -v /tmp/skydivetests-dockervpp-sockets/:/run/othersockets/ --privileged --name %s %s", vpp2Container, dockerImageWithRunningVPP), false},
170+
171+
// waiting for VPPs to start inside containers
172+
{fmt.Sprintf(vppWaitScript, 30, vpp1Container), true},
173+
{fmt.Sprintf(vppWaitScript, 30, vpp2Container), true},
174+
175+
// creating memif tunnel
176+
{fmt.Sprintf("docker exec %s vppctl create memif socket id 1 filename /run/othersockets/another-memif.sock", vpp1Container), true},
177+
{fmt.Sprintf("docker exec %s vppctl create interface memif socket-id 1 id 0 master", vpp1Container), true},
178+
{fmt.Sprintf("docker exec %s vppctl set int state memif1/0 up", vpp1Container), true},
179+
{fmt.Sprintf("docker exec %s vppctl create memif socket id 1 filename /run/othersockets/another-memif.sock", vpp2Container), true},
180+
{fmt.Sprintf("docker exec %s vppctl create interface memif socket-id 1 id 0 slave", vpp2Container), true},
181+
{fmt.Sprintf("docker exec %s vppctl set int state memif1/0 up", vpp2Container), true},
182+
},
183+
184+
tearDownCmds: []Cmd{
185+
// removing memif socket file (it was created by VPP,but removing it from VPP doesn't remove the physical
186+
// file->removing reference from VPPs and removing it on docker container level to prevent permission problems)
187+
{fmt.Sprintf("docker exec %s vppctl delete interface memif memif1/0", vpp1Container), true},
188+
{fmt.Sprintf("docker exec %s vppctl delete interface memif memif1/0", vpp2Container), true},
189+
{fmt.Sprintf("docker exec %s vppctl delete memif socket id 1", vpp1Container), true},
190+
{fmt.Sprintf("docker exec %s vppctl delete memif socket id 1", vpp2Container), true},
191+
{fmt.Sprintf("docker exec %s rm -rf /run/othersockets/another-memif.sock", vpp1Container), true},
192+
193+
// removing docker containers
194+
{fmt.Sprintf("docker rm -f %s", vpp1Container), false},
195+
{fmt.Sprintf("docker rm -f %s", vpp2Container), false},
196+
197+
// removing container-shared folder for memif socket file
198+
{"rm -rf /tmp/skydivetests-dockervpp-sockets", true},
199+
},
200+
201+
mode: Replay,
202+
203+
checks: []CheckFunction{func(c *CheckContext) error {
204+
return assertOneEndNode(c, c.gremlin.V().Has("Type", "vpp", "Program", "vpe").
205+
Out("Type", "interface", "Name", "memif1/0", "VPP.SocketFilename", "/run/othersockets/another-memif.sock", "VPP.Master", true).
206+
Out("Type", "interface", "Name", "memif1/0", "VPP.SocketFilename", "/run/othersockets/another-memif.sock", "VPP.Master", false).
207+
In("Type", "vpp", "Program", "vpe"))
208+
}},
209+
}
210+
211+
RunTest(t, test)
212+
}
213+
214+
func assertOneEndNode(c *CheckContext, queryString gremlin.QueryString) error {
215+
nodes, err := c.gh.GetNodes(queryString)
216+
if err != nil {
217+
return err
218+
}
219+
220+
if len(nodes) != 1 {
221+
return fmt.Errorf("expected 1 end node, got %+v", nodes)
222+
}
223+
224+
return nil
225+
}

0 commit comments

Comments
 (0)