blob: b35a8b1b23536b0c23bc0294e8f275ca111423e5 [file] [log] [blame]
Joey Armstrong65405412022-11-22 10:43:06 -05001// -*- groovy -*-
2// Copyright 2021-2022 Open Networking Foundation (ONF) and the ONF Contributors
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16// voltha-2.x e2e tests for openonu-go
17// uses bbsim to simulate OLT/ONUs
18
19library identifier: 'cord-jenkins-libraries@master',
20 retriever: modernSCM([
21 $class: 'GitSCMSource',
22 remote: 'https://gerrit.opencord.org/ci-management.git'
23])
24
25def clusterName = "kind-ci"
26
27def execute_test(testTarget, workflow, testLogging, teardown, testSpecificHelmFlags = "") {
Joey Armstrong293e16b2022-11-26 20:16:33 -050028 def infraNamespace = "default"
29 def volthaNamespace = "voltha"
30 def logsDir = "$WORKSPACE/${testTarget}"
Joey Armstrong65405412022-11-22 10:43:06 -050031
Joey Armstrong293e16b2022-11-26 20:16:33 -050032 stage('IAM')
Joey Armstrong65405412022-11-22 10:43:06 -050033 {
Joey Armstrong293e16b2022-11-26 20:16:33 -050034 script
35 {
36 String iam = [
37 'ci-management',
38 'jjb',
39 'pipeline',
40 'voltha',
41 'voltha-11',
42 'bbsim-tests.groovy'
43 ].join('/')
44 println("** ${iam}: ENTER")
45 println("** ${iam}: LEAVE")
46 }
47 }
Joey Armstrong65405412022-11-22 10:43:06 -050048
49 stage('Cleanup') {
50 if (teardown) {
51 timeout(15) {
52 script {
53 helmTeardown(["default", infraNamespace, volthaNamespace])
54 }
55 timeout(1) {
56 sh returnStdout: false, script: '''
57 # remove orphaned port-forward from different namespaces
58 ps aux | grep port-forw | grep -v grep | awk '{print $2}' | xargs --no-run-if-empty kill -9 || true
59 '''
60 }
61 }
62 }
63 }
64 stage('Deploy common infrastructure') {
65 sh '''
66 helm repo add onf https://charts.opencord.org
67 helm repo update
68 if [ ${withMonitoring} = true ] ; then
69 helm install nem-monitoring onf/nem-monitoring \
70 --set prometheus.alertmanager.enabled=false,prometheus.pushgateway.enabled=false \
71 --set kpi_exporter.enabled=false,dashboards.xos=false,dashboards.onos=false,dashboards.aaa=false,dashboards.voltha=false
72 fi
73 '''
74 }
75 stage('Deploy Voltha') {
76 if (teardown) {
77 timeout(10) {
78 script {
79
80 sh """
81 mkdir -p ${logsDir}
82 _TAG=kail-startup kail -n ${infraNamespace} -n ${volthaNamespace} > ${logsDir}/onos-voltha-startup-combined.log &
83 """
84
85 // if we're downloading a voltha-helm-charts patch, then install from a local copy of the charts
86 def localCharts = false
87 if (volthaHelmChartsChange != "" || gerritProject == "voltha-helm-charts") {
88 localCharts = true
89 }
90
91 // NOTE temporary workaround expose ONOS node ports
92 def localHelmFlags = extraHelmFlags.trim() + " --set global.log_level=${logLevel.toUpperCase()} " +
93 " --set onos-classic.onosSshPort=30115 " +
94 " --set onos-classic.onosApiPort=30120 " +
95 " --set onos-classic.onosOfPort=31653 " +
96 " --set onos-classic.individualOpenFlowNodePorts=true " + testSpecificHelmFlags
97
98 if (gerritProject != "") {
99 localHelmFlags = "${localHelmFlags} " + getVolthaImageFlags("${gerritProject}")
100 }
101
102 volthaDeploy([
103 infraNamespace: infraNamespace,
104 volthaNamespace: volthaNamespace,
105 workflow: workflow.toLowerCase(),
106 withMacLearning: enableMacLearning.toBoolean(),
107 extraHelmFlags: localHelmFlags,
108 localCharts: localCharts,
109 bbsimReplica: olts.toInteger(),
110 dockerRegistry: registry,
111 ])
112 }
113
114 // stop logging
115 sh """
116 P_IDS="\$(ps e -ww -A | grep "_TAG=kail-startup" | grep -v grep | awk '{print \$1}')"
117 if [ -n "\$P_IDS" ]; then
118 echo \$P_IDS
119 for P_ID in \$P_IDS; do
120 kill -9 \$P_ID
121 done
122 fi
123 cd ${logsDir}
124 gzip -k onos-voltha-startup-combined.log
125 rm onos-voltha-startup-combined.log
126 """
127 }
128 sh """
129 JENKINS_NODE_COOKIE="dontKillMe" _TAG="voltha-voltha-api" bash -c "while true; do kubectl port-forward --address 0.0.0.0 -n ${volthaNamespace} svc/voltha-voltha-api 55555:55555; done"&
130 JENKINS_NODE_COOKIE="dontKillMe" _TAG="voltha-infra-etcd" bash -c "while true; do kubectl port-forward --address 0.0.0.0 -n ${infraNamespace} svc/voltha-infra-etcd 2379:2379; done"&
131 JENKINS_NODE_COOKIE="dontKillMe" _TAG="voltha-infra-kafka" bash -c "while true; do kubectl port-forward --address 0.0.0.0 -n ${infraNamespace} svc/voltha-infra-kafka 9092:9092; done"&
132 bbsimDmiPortFwd=50075
133 for i in {0..${olts.toInteger() - 1}}; do
134 JENKINS_NODE_COOKIE="dontKillMe" _TAG="bbsim\${i}" bash -c "while true; do kubectl port-forward --address 0.0.0.0 -n ${volthaNamespace} svc/bbsim\${i} \${bbsimDmiPortFwd}:50075; done"&
135 ((bbsimDmiPortFwd++))
136 done
137 if [ ${withMonitoring} = true ] ; then
138 JENKINS_NODE_COOKIE="dontKillMe" _TAG="nem-monitoring-prometheus-server" bash -c "while true; do kubectl port-forward --address 0.0.0.0 -n default svc/nem-monitoring-prometheus-server 31301:80; done"&
139 fi
140 ps aux | grep port-forward
141 """
142 // setting ONOS log level
143 script {
144 setOnosLogLevels([
145 onosNamespace: infraNamespace,
146 apps: [
147 'org.opencord.dhcpl2relay',
148 'org.opencord.olt',
149 'org.opencord.aaa',
150 'org.opencord.maclearner',
151 'org.onosproject.net.flowobjective.impl.FlowObjectiveManager',
152 'org.onosproject.net.flowobjective.impl.InOrderFlowObjectiveManager'
153 ],
154 logLevel: logLevel
155 ])
156 }
157 }
158 }
159 stage('Run test ' + testTarget + ' on ' + workflow + ' workFlow') {
160 sh """
161 if [ ${withMonitoring} = true ] ; then
162 mkdir -p $WORKSPACE/voltha-pods-mem-consumption-${workflow}
163 cd $WORKSPACE/voltha-system-tests
164 make vst_venv
165 source ./vst_venv/bin/activate || true
166 # Collect initial memory consumption
167 python scripts/mem_consumption.py -o $WORKSPACE/voltha-pods-mem-consumption-${workflow} -a 0.0.0.0:31301 -n ${volthaNamespace} || true
168 fi
169 """
170 sh """
171 mkdir -p ${logsDir}
172 export ROBOT_MISC_ARGS="-d ${logsDir} ${params.extraRobotArgs} "
173 ROBOT_MISC_ARGS+="-v ONOS_SSH_PORT:30115 -v ONOS_REST_PORT:30120 -v NAMESPACE:${volthaNamespace} -v INFRA_NAMESPACE:${infraNamespace} -v container_log_dir:${logsDir} -v logging:${testLogging}"
174 export KVSTOREPREFIX=voltha/voltha_voltha
175
176 make -C $WORKSPACE/voltha-system-tests ${testTarget} || true
177 """
178 getPodsInfo("${logsDir}")
179 sh """
180 set +e
181 # collect logs collected in the Robot Framework StartLogging keyword
182 cd ${logsDir}
183 gzip *-combined.log || true
184 rm *-combined.log || true
185 """
186 sh """
187 if [ ${withMonitoring} = true ] ; then
188 cd $WORKSPACE/voltha-system-tests
189 source ./vst_venv/bin/activate || true
190 # Collect memory consumption of voltha pods once all the tests are complete
191 python scripts/mem_consumption.py -o $WORKSPACE/voltha-pods-mem-consumption-${workflow} -a 0.0.0.0:31301 -n ${volthaNamespace} || true
192 fi
193 """
194 }
195}
196
197def collectArtifacts(exitStatus) {
198 getPodsInfo("$WORKSPACE/${exitStatus}")
199 sh """
200 kubectl logs -n voltha -l app.kubernetes.io/part-of=voltha > $WORKSPACE/${exitStatus}/voltha.log || true
201 """
202 archiveArtifacts artifacts: '**/*.log,**/*.gz,**/*.txt,**/*.html,**/voltha-pods-mem-consumption-att/*,**/voltha-pods-mem-consumption-dt/*,**/voltha-pods-mem-consumption-tt/*'
203 sh '''
204 sync
205 pkill kail || true
206 which voltctl
207 md5sum $(which voltctl)
208 '''
209 step([$class: 'RobotPublisher',
210 disableArchiveOutput: false,
211 logFileName: "**/*/log*.html",
212 otherFiles: '',
213 outputFileName: "**/*/output*.xml",
214 outputPath: '.',
215 passThreshold: 100,
216 reportFileName: "**/*/report*.html",
217 unstableThreshold: 0,
218 onlyCritical: true]);
219}
220
221pipeline {
222
223 /* no label, executor is determined by JJB */
224 agent {
225 label "${params.buildNode}"
226 }
227 options {
228 timeout(time: "${timeout}", unit: 'MINUTES')
229 }
230 environment {
231 KUBECONFIG="$HOME/.kube/kind-${clusterName}"
232 VOLTCONFIG="$HOME/.volt/config"
233 PATH="$PATH:$WORKSPACE/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
234 DIAGS_PROFILE="VOLTHA_PROFILE"
235 SSHPASS="karaf"
236 }
237 stages {
238 stage('Download Code') {
239 steps {
240 getVolthaCode([
241 branch: "${branch}",
242 gerritProject: "${gerritProject}",
243 gerritRefspec: "${gerritRefspec}",
244 volthaSystemTestsChange: "${volthaSystemTestsChange}",
245 volthaHelmChartsChange: "${volthaHelmChartsChange}",
246 ])
247 }
248 }
249 stage('Build patch') {
250 // build the patch only if gerritProject is specified
251 when {
252 expression {
253 return !gerritProject.isEmpty()
254 }
255 }
256 steps {
257 // NOTE that the correct patch has already been checked out
258 // during the getVolthaCode step
259 buildVolthaComponent("${gerritProject}")
260 }
261 }
262 stage('Create K8s Cluster') {
263 steps {
264 script {
265 def clusterExists = sh returnStdout: true, script: """
266 kind get clusters | grep ${clusterName} | wc -l
267 """
268 if (clusterExists.trim() == "0") {
269 createKubernetesCluster([nodes: 3, name: clusterName])
270 }
271 }
272 }
273 }
274 stage('Replace voltctl') {
275 // if the project is voltctl override the downloaded one with the built one
276 when {
277 expression {
278 return gerritProject == "voltctl"
279 }
280 }
281 steps{
282 sh """
283 mv `ls $WORKSPACE/voltctl/release/voltctl-*-linux-amd*` $WORKSPACE/bin/voltctl
284 chmod +x $WORKSPACE/bin/voltctl
285 """
286 }
287 }
288 stage('Load image in kind nodes') {
289 when {
290 expression {
291 return !gerritProject.isEmpty()
292 }
293 }
294 steps {
295 loadToKind()
296 }
297 }
298 stage('Parse and execute tests') {
299 steps {
300 script {
301 def tests = readYaml text: testTargets
302
303 for(int i = 0;i<tests.size();i++) {
304 def test = tests[i]
305 def target = test["target"]
306 def workflow = test["workflow"]
307 def flags = test["flags"]
308 def teardown = test["teardown"].toBoolean()
309 def logging = test["logging"].toBoolean()
310 def testLogging = 'False'
311 if (logging) {
312 testLogging = 'True'
313 }
314 println "Executing test ${target} on workflow ${workflow} with logging ${testLogging} and extra flags ${flags}"
315 execute_test(target, workflow, testLogging, teardown, flags)
316 }
317 }
318 }
319 }
320 }
321 post {
322 aborted {
323 collectArtifacts("aborted")
324 }
325 failure {
326 collectArtifacts("failed")
327 }
328 always {
329 collectArtifacts("always")
330 }
331 }
332}