blob: d400681edb9e4a353fcc3b660d6588e6ec27ac6f [file] [log] [blame]
Matteo Scandolo9b644ba2021-04-19 11:21:07 -07001
2// Copyright 2017-present Open Networking Foundation
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// used to deploy VOLTHA and configure ONOS physical PODs
16// NOTE we are importing the library even if it's global so that it's
17// easier to change the keywords during a replay
18library identifier: 'cord-jenkins-libraries@master',
19 retriever: modernSCM([
20 $class: 'GitSCMSource',
21 remote: 'https://gerrit.opencord.org/ci-management.git'
22])
23def infraNamespace = "infra"
24def volthaNamespace = "voltha"
25def clusterName = "kind-ci"
26pipeline {
27 /* no label, executor is determined by JJB */
28 agent {
29 label "${params.buildNode}"
30 }
31 options {
32 timeout(time: 120, unit: 'MINUTES')
33 }
34 environment {
35 PATH="$PATH:$WORKSPACE/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
36 KUBECONFIG="$HOME/.kube/kind-${clusterName}"
37 VOLTCONFIG="$HOME/.volt/config"
38 }
39 stages{
40 stage('Download Code') {
41 steps {
42 getVolthaCode([
43 branch: "${branch}",
44 gerritProject: "${gerritProject}",
45 gerritRefspec: "${gerritRefspec}",
46 volthaSystemTestsChange: "${volthaSystemTestsChange}",
47 volthaHelmChartsChange: "${volthaHelmChartsChange}",
48 ])
49 }
50 }
51 stage ("Parse deployment configuration file") {
52 steps {
53 sh returnStdout: true, script: "rm -rf ${configBaseDir}"
54 sh returnStdout: true, script: "git clone -b master ${cordRepoUrl}/${configBaseDir}"
55 script {
56 if ( params.workflow.toUpperCase() == "DT" ) {
57 deployment_config = readYaml file: "${configBaseDir}/${configDeploymentDir}/${configFileName}-DT.yaml"
58 }
59 else if ( params.workflow.toUpperCase() == "TT" ) {
60 deployment_config = readYaml file: "${configBaseDir}/${configDeploymentDir}/${configFileName}-TT.yaml"
61 }
62 else {
63 deployment_config = readYaml file: "${configBaseDir}/${configDeploymentDir}/${configFileName}.yaml"
64 }
65 }
66 }
67 }
68 stage('Clean up') {
69 steps {
70 timeout(15) {
71 script {
72 helmTeardown(["default", infraNamespace, volthaNamespace])
73 }
74 timeout(1) {
75 sh returnStdout: false, script: '''
76 # remove orphaned port-forward from different namespaces
77 ps aux | grep port-forw | grep -v grep | awk '{print $2}' | xargs --no-run-if-empty kill -9
78 '''
79 }
80 }
81 }
82 }
83 stage('Build patch') {
84 steps {
85 // NOTE that the correct patch has already been checked out
86 // during the getVolthaCode step
87 buildVolthaComponent("${gerritProject}")
88 }
89 }
90 stage('Create K8s Cluster') {
91 steps {
92 script {
93 def clusterExists = sh returnStdout: true, script: """
94 kind get clusters | grep ${clusterName} | wc -l
95 """
96 if (clusterExists.trim() == "0") {
97 createKubernetesCluster([nodes: 3, name: clusterName])
98 }
99 }
100 }
101 }
102 stage('Load image in kind nodes') {
103 steps {
104 loadToKind()
105 }
106 }
107 stage('Install Voltha') {
108 steps {
109 timeout(20) {
110 script {
111 imageFlags = getVolthaImageFlags(gerritProject)
112 // if we're downloading a voltha-helm-charts patch, then install from a local copy of the charts
113 def localCharts = false
114 if (volthaHelmChartsChange != "" || gerritProject == "voltha-helm-charts") {
115 localCharts = true
116 }
117 def extraHelmFlags = "-f $WORKSPACE/${configBaseDir}/${configKubernetesDir}/voltha/${configFileName}.yml ${imageFlags} "
118 // NOTE temporary workaround expose ONOS node ports (pod-config needs to be updated to contain these values)
119 extraHelmFlags = extraHelmFlags + "--set onos-classic.onosSshPort=30115 " +
120 "--set onos-classic.onosApiPort=30120 " +
121 "--set onos-classic.onosOfPort=31653 " +
122 "--set onos-classic.individualOpenFlowNodePorts=true "
123 volthaDeploy([
124 workflow: workFlow.toLowerCase(),
125 extraHelmFlags: extraHelmFlags,
126 localCharts: localCharts,
127 kubeconfig: "$WORKSPACE/${configBaseDir}/${configKubernetesDir}/${configFileName}.conf",
128 onosReplica: 3,
129 atomixReplica: 3,
130 kafkaReplica: 3,
131 etcdReplica: 3,
132 ])
133 }
134 // start logging
135 sh """
136 mkdir -p $WORKSPACE/${workFlow}
137 _TAG=kail-${workFlow} kail -n infra -n voltha > $WORKSPACE/${workFlow}/onos-voltha-combined.log &
138 """
139 sh """
140 JENKINS_NODE_COOKIE="dontKillMe" bash -c "while true; do kubectl port-forward --address 0.0.0.0 -n ${volthaNamespace} svc/voltha-voltha-api 55555:55555; done"&
141 JENKINS_NODE_COOKIE="dontKillMe" bash -c "while true; do kubectl port-forward --address 0.0.0.0 -n ${infraNamespace} svc/voltha-infra-etcd 2379:2379; done"&
142 JENKINS_NODE_COOKIE="dontKillMe" bash -c "while true; do kubectl port-forward --address 0.0.0.0 -n ${infraNamespace} svc/voltha-infra-kafka 9092:9092; done"&
143 ps aux | grep port-forward
144 """
145 getPodsInfo("$WORKSPACE")
146 }
147 }
148 }
149 stage('Deploy Kafka Dump Chart') {
150 steps {
151 script {
152 sh returnStdout: false, script: """
153 helm repo add cord https://charts.opencord.org
154 helm repo update
155 if helm version -c --short|grep v2 -q; then
156 helm install -n voltha-kafka-dump cord/voltha-kafka-dump
157 else
158 helm install voltha-kafka-dump cord/voltha-kafka-dump
159 fi
160 """
161 }
162 }
163 }
164 stage('Push Tech-Profile') {
165 when {
166 expression { params.profile != "Default" }
167 }
168 steps {
169 sh returnStdout: false, script: """
170 etcd_container=\$(kubectl get pods -n voltha | grep voltha-etcd-cluster | awk 'NR==1{print \$1}')
171 kubectl cp $WORKSPACE/voltha-system-tests/tests/data/TechProfile-${profile}.json voltha/\$etcd_container:/tmp/flexpod.json
172 kubectl exec -it \$etcd_container -n voltha -- /bin/sh -c 'cat /tmp/flexpod.json | ETCDCTL_API=3 etcdctl put service/voltha/technology_profiles/XGS-PON/64'
173 """
174 }
175 }
176
177 stage('Push Sadis-config') {
178 steps {
179 sh returnStdout: false, script: """
180 ssh-keygen -R [${deployment_config.nodes[0].ip}]:30115
181 ssh-keyscan -p 30115 -H ${deployment_config.nodes[0].ip} >> ~/.ssh/known_hosts
182 sshpass -p karaf ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 30115 karaf@${deployment_config.nodes[0].ip} "log:set TRACE org.opencord.dhcpl2relay"
183 sshpass -p karaf ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 30115 karaf@${deployment_config.nodes[0].ip} "log:set TRACE org.opencord.aaa"
184 sshpass -p karaf ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 30115 karaf@${deployment_config.nodes[0].ip} "log:set TRACE org.opencord.olt"
185 sshpass -p karaf ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 30115 karaf@${deployment_config.nodes[0].ip} "log:set DEBUG org.onosproject.net.flowobjective.impl.FlowObjectiveManager"
186 sshpass -p karaf ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 30115 karaf@${deployment_config.nodes[0].ip} "log:set DEBUG org.onosproject.net.flowobjective.impl.InOrderFlowObjectiveManager"
187
188 if [[ "${workFlow.toUpperCase()}" == "DT" ]]; then
189 curl -sSL --user karaf:karaf -X POST -H Content-Type:application/json http://${deployment_config.nodes[0].ip}:30120/onos/v1/network/configuration --data @$WORKSPACE/voltha-system-tests/tests/data/${configFileName}-sadis-DT.json
190 elif [[ "${workFlow.toUpperCase()}" == "TT" ]]; then
191 curl -sSL --user karaf:karaf -X POST -H Content-Type:application/json http://${deployment_config.nodes[0].ip}:30120/onos/v1/network/configuration --data @$WORKSPACE/voltha-system-tests/tests/data/${configFileName}-sadis-TT.json
192 else
193 # this is the ATT case, rename the file in *-sadis-ATT.json so that we can avoid special cases and just load the file
194 curl -sSL --user karaf:karaf -X POST -H Content-Type:application/json http://${deployment_config.nodes[0].ip}:30120/onos/v1/network/configuration --data @$WORKSPACE/voltha-system-tests/tests/data/${configFileName}-sadis.json
195 fi
196 """
197 }
198 }
199 stage('Reinstall OLT software') {
200 when {
201 expression { params.reinstallOlt }
202 }
203 steps {
204 script {
205 deployment_config.olts.each { olt ->
206 sh returnStdout: false, script: "sshpass -p ${olt.pass} ssh -l ${olt.user} ${olt.ip} 'dpkg --remove asfvolt16 && dpkg --purge asfvolt16'"
207 waitUntil {
208 olt_sw_present = sh returnStdout: true, script: "sshpass -p ${olt.pass} ssh -l ${olt.user} ${olt.ip} 'dpkg --list | grep asfvolt16 | wc -l'"
209 return olt_sw_present.toInteger() == 0
210 }
211 if ( params.branch == 'voltha-2.3' ) {
212 oltDebVersion = oltDebVersionVoltha23
213 } else {
214 oltDebVersion = oltDebVersionMaster
215 }
216 sh returnStdout: false, script: "sshpass -p ${olt.pass} ssh -l ${olt.user} ${olt.ip} 'dpkg --install ${oltDebVersion}'"
217 waitUntil {
218 olt_sw_present = sh returnStdout: true, script: "sshpass -p ${olt.pass} ssh -l ${olt.user} ${olt.ip} 'dpkg --list | grep asfvolt16 | wc -l'"
219 return olt_sw_present.toInteger() == 1
220 }
221 if ( olt.fortygig ) {
222 // If the OLT is connected to a 40G switch interface, set the NNI port to be downgraded
223 sh returnStdout: false, script: "sshpass -p ${olt.pass} ssh -l ${olt.user} ${olt.ip} 'echo port ce128 sp=40000 >> /broadcom/qax.soc ; /opt/bcm68620/svk_init.sh'"
224 }
225 }
226 }
227 }
228 }
229
230 stage('Restart OLT processes') {
231 steps {
232 script {
233 deployment_config.olts.each { olt ->
234 sh returnStdout: false, script: """
235 ssh-keyscan -H ${olt.ip} >> ~/.ssh/known_hosts
236 sshpass -p ${olt.pass} ssh -l ${olt.user} ${olt.ip} 'rm -f /var/log/openolt.log; rm -f /var/log/dev_mgmt_daemon.log; reboot'
237 sleep 120
238 """
239 waitUntil {
240 onu_discovered = sh returnStdout: true, script: "sshpass -p ${olt.pass} ssh -l ${olt.user} ${olt.ip} 'grep \"onu discover indication\" /var/log/openolt.log | wc -l'"
241 return onu_discovered.toInteger() > 0
242 }
243 }
244 }
245 }
246 }
247 stage('Run E2E Tests') {
248 steps {
249 script {
250 if ( params.workflow.toUpperCase() == "DT" ) {
251 robotConfigFile = "${configBaseDir}/${configDeploymentDir}/${configFileName}-DT.yaml"
252 }
253 else if ( params.workflow.toUpperCase() == "TT" ) {
254 robotConfigFile = "${configBaseDir}/${configDeploymentDir}/${configFileName}-TT.yaml"
255 }
256 else {
257 robotConfigFile = "${configBaseDir}/${configDeploymentDir}/${configFileName}.yaml"
258 }
259 }
260 sh returnStdout: false, script: """
261 mkdir -p $WORKSPACE/RobotLogs
262
263 export ROBOT_CONFIG_FILE="$WORKSPACE/${robotConfigFile}"
264 export ROBOT_MISC_ARGS="${params.extraRobotArgs} --removekeywords wuks -d $WORKSPACE/RobotLogs -v container_log_dir:$WORKSPACE "
265 export ROBOT_FILE="Voltha_PODTests.robot"
266
267 # If the Gerrit comment contains a line with "functional tests" then run the full
268 # functional test suite. This covers tests tagged either 'sanity' or 'functional'.
269 # Note: Gerrit comment text will be prefixed by "Patch set n:" and a blank line
270 REGEX="functional tests"
271 if [[ "${gerritComment}" =~ \$REGEX ]]; then
272 ROBOT_MISC_ARGS+="-i functional"
273 fi
274 # Likewise for dataplane tests
275 REGEX="dataplane tests"
276 if [[ "${gerritComment}" =~ \$REGEX ]]; then
277 ROBOT_MISC_ARGS+="-i dataplane"
278 fi
279
280 make -C $WORKSPACE/voltha-system-tests voltha-test || true
281 """
282 }
283 }
284 }
285 post {
286 always {
287 // stop logging
288 sh """
289 P_IDS="\$(ps e -ww -A | grep "_TAG=kail-${workFlow}" | grep -v grep | awk '{print \$1}')"
290 if [ -n "\$P_IDS" ]; then
291 echo \$P_IDS
292 for P_ID in \$P_IDS; do
293 kill -9 \$P_ID
294 done
295 fi
296 gzip $WORKSPACE/${workFlow}/onos-voltha-combined.log || true
297 """
298 step([$class: 'RobotPublisher',
299 disableArchiveOutput: false,
300 logFileName: 'RobotLogs/log*.html',
301 otherFiles: '',
302 outputFileName: 'RobotLogs/output*.xml',
303 outputPath: '.',
304 passThreshold: 100,
305 reportFileName: 'RobotLogs/report*.html',
306 unstableThreshold: 0]);
307 archiveArtifacts artifacts: '**/*.txt,**/*.gz,*.gz'
308 }
309 }
310}
311
312// refs/changes/06/24206/5