blob: 4604bca7b28a370d9f1423412fbee5febf720bb4 [file] [log] [blame]
Joey Armstrong96158a92022-11-25 10:36:06 -05001#!/usr/bin/env groovy
Joey Armstrong3d444c62022-11-26 21:42:20 -05002// -----------------------------------------------------------------------
Joey Armstrongaf679da2023-01-31 14:22:41 -05003// Copyright 2021-2023 Open Networking Foundation (ONF) and the ONF Contributors
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
Joey Armstrong3d444c62022-11-26 21:42:20 -050016// -----------------------------------------------------------------------
Joey Armstrong96158a92022-11-25 10:36:06 -050017
Joey Armstrong3d444c62022-11-26 21:42:20 -050018// -----------------------------------------------------------------------
19// -----------------------------------------------------------------------
Joey Armstrong74ec08c2023-08-31 11:25:57 -040020String getIam(String func) {
Joey Armstrong7987c112022-12-05 12:42:43 -050021 // Cannot rely on a stack trace due to jenkins manipulation
Joey Armstrong3d444c62022-11-26 21:42:20 -050022 String src = 'vars/waitForAdapters.groovy'
23 String iam = [src, func].join('::')
Joey Armstrongf0c76902022-11-28 17:14:45 -050024 return iam
Joey Armstrong3d444c62022-11-26 21:42:20 -050025}
Andrea Campanella45b8eb72021-09-28 10:50:01 +020026
Joey Armstrong3d444c62022-11-26 21:42:20 -050027// -----------------------------------------------------------------------
Joey Armstrong74ec08c2023-08-31 11:25:57 -040028// Intent: Log progress message
Joey Armstrong3d444c62022-11-26 21:42:20 -050029// -----------------------------------------------------------------------
Joey Armstrong74ec08c2023-08-31 11:25:57 -040030void enter(String name) {
31 // Announce ourselves for log usability
32 String iam = getIam(name)
33 println("${iam}: ENTER")
34 return
35}
Joey Armstrong3d444c62022-11-26 21:42:20 -050036
Joey Armstrong74ec08c2023-08-31 11:25:57 -040037// -----------------------------------------------------------------------
38// Intent: Log progress message
39// -----------------------------------------------------------------------
40void leave(String name) {
41 // Announce ourselves for log usability
42 String iam = getIam(name)
43 println("${iam}: LEAVE")
44 return
45}
46
47// -----------------------------------------------------------------------
48// -----------------------------------------------------------------------
49def getAdapters() {
Joey Armstrong74ec08c2023-08-31 11:25:57 -040050 String adapters = ''
51
52 try {
53 adapters = sh(
Joey Armstrong3d444c62022-11-26 21:42:20 -050054 script: 'voltctl adapter list --format "{{gosince .LastCommunication}}"',
55 returnStdout: true,
56 ).trim()
57 }
Joey Armstrong74ec08c2023-08-31 11:25:57 -040058 catch (err) {
Joey Armstrong3d444c62022-11-26 21:42:20 -050059 // in some older versions of voltctl the command results in
60 // ERROR: Unexpected error while attempting to format results
61 // as table : template: output:1: function "gosince" not defined
62 // if that's the case we won't be able to check the timestamp so
63 // it's useless to wait
64 println("voltctl can't parse LastCommunication, skip waiting")
Joey Armstrong74ec08c2023-08-31 11:25:57 -040065 adapters = 'SKIP' // why not just retry a few times (?)
Joey Armstrong3d444c62022-11-26 21:42:20 -050066 }
67
Joey Armstronge93c3fa2023-09-11 09:34:24 -040068 leave("returned $adapters")
Joey Armstrong3d444c62022-11-26 21:42:20 -050069 return adapters
70}
71
72// -----------------------------------------------------------------------
Joey Armstrong14a67a12022-11-28 12:28:23 -050073// Intent: Interrogate adapter states to determine if we should continue
74// looping waiting for adapter to start. Passed values must all be
75// Integral, Valid and within range to assert we are done waiting.
76// Function will return incomplete at the first sign of an invalid value.
77// -----------------------------------------------------------------------
78// NOTE: list.find{} was replaced with a for loop to simplify
79// early loop termination and return.
80// -----------------------------------------------------------------------
81// RETURN: scalar
82// 'DOUBLE-DIGIT' - value exceeds 0-5sec response window.
83// 'NON-NUMERIC' - garbage in the stream (letter, symbol, ctrl)
84// 'NULL' - empty or null string detected
85// 'VALID' - succes, all adapters are functional
86// 'SIX-NINE' - detected a single numeric digit between 6 and 9.
87// -----------------------------------------------------------------------
88def getAdaptersState(String adapters0)
89{
90 String iam = getIam('getAdaptersState')
91 Boolean debug = true // for now
92
93 def adapters = adapters0.split('\n')
94
95 String ans = null
96 def found = []
Joey Armstrong74ec08c2023-08-31 11:25:57 -040097 for(i=0; i<adapters.size(); i++) {
98 String elapsed = adapters[i]
99 if (debug) {
100 println("** ${iam} Checking elapsed[$i]: $elapsed")
101 }
Joey Armstrong14a67a12022-11-28 12:28:23 -0500102
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400103 if (! elapsed) { // empty string or null
104 ans = 'NULL'
105 break
106 }
Joey Armstrong14a67a12022-11-28 12:28:23 -0500107
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400108 Integer size = elapsed.length()
109 if (size > 2) { // 463765h58m52(s)
110 // higlander: there can be only one
111 ans = 'DOUBLE-DIGIT'
112 break
113 }
Joey Armstrong14a67a12022-11-28 12:28:23 -0500114
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400115 if (elapsed.endsWith('s')) {
116 // safer than replaceAll('s'): ssss1s => 1
117 elapsed = elapsed.substring(0, size-1)
118 }
Joey Armstrong14a67a12022-11-28 12:28:23 -0500119
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400120 // Line noise guard: 'a', 'f', '#', '!'
121 if (! elapsed.isInteger()) {
122 ans = 'NON-NUMERIC'
123 break
124 }
Joey Armstrong14a67a12022-11-28 12:28:23 -0500125
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400126 // Is value in range:
127 // discard negative integers as just plain wonky.
128 // HMMM(?): zero/no latency response is kinda odd to include imho.
129 Integer val = elapsed.toInteger()
130 if (5 >= val && val >= 0) {
131 found.add(elapsed)
132 }
133 else {
134 ans = 'SIX-NINE'
135 break
136 }
Joey Armstrong14a67a12022-11-28 12:28:23 -0500137 } // for()
138
139 // Declare success IFF all values are:
140 // o integral
141 // o valid
142 // o within range
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400143 if (ans == null) {
144 Integer got = found.size()
145 Integer exp = adapters.size()
146 ans = (! exp) ? 'NO-ADAPTERS'
Joey Armstrong14a67a12022-11-28 12:28:23 -0500147 : (got == exp) ? 'VALID'
148 : 'CONTINUE'
149 }
150
Joey Armstronge93c3fa2023-09-11 09:34:24 -0400151
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400152 if (debug) {
Joey Armstronge93c3fa2023-09-11 09:34:24 -0400153 leave("return: [$ans]")
Joey Armstrong7987c112022-12-05 12:42:43 -0500154 }
Joey Armstrong14a67a12022-11-28 12:28:23 -0500155 return ans
156} // getAdaptersState
157
158// -----------------------------------------------------------------------
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400159// Intent: Poll until adapter status is known.
Joey Armstrong3d444c62022-11-26 21:42:20 -0500160// -----------------------------------------------------------------------
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400161def process(Map config) {
Joey Armstrong3d444c62022-11-26 21:42:20 -0500162 String iam = getIam('process')
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400163 enter('process')
Joey Armstrong96158a92022-11-25 10:36:06 -0500164
Andrea Campanella45b8eb72021-09-28 10:50:01 +0200165 def defaultConfig = [
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400166 volthaNamespace : 'voltha',
167 stackName : 'voltha',
168 adaptersToWait : 2,
Andrea Campanella45b8eb72021-09-28 10:50:01 +0200169 ]
170
Andrea Campanella45b8eb72021-09-28 10:50:01 +0200171 def cfg = defaultConfig + config
172
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400173 if (cfg.adaptersToWait == 0) {
174 //no need to wait
175 println "No need to wait for adapters to be registered"
176 return
Andrea Campanella365ea1e2021-09-28 10:50:01 +0200177 }
178
Joey Armstrong3d444c62022-11-26 21:42:20 -0500179 println("** ${iam}: Wait for adapters to be registered")
Andrea Campanella45b8eb72021-09-28 10:50:01 +0200180
181 // guarantee that at least the specified number of adapters are registered with VOLTHA before proceeding
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400182 sh(label : 'waitForAdapters: loop until adapter list',
183 script : """
184# set +x
Andrea Campanella45b8eb72021-09-28 10:50:01 +0200185 adapters=\$(voltctl adapter list -q | wc -l)
186 while [[ \$adapters -lt ${cfg.adaptersToWait} ]]; do
187 sleep 5
188 adapters=\$(voltctl adapter list -q | wc -l)
189 done
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400190
191 cat << EOM
192** -----------------------------------------------------------------------
193** ${iam}: Available adapters:
194** -----------------------------------------------------------------------
195EOM
196 voltctl adapter list -q
197 """)
Andrea Campanella45b8eb72021-09-28 10:50:01 +0200198
Matteo Scandolo28722ea2021-10-01 15:48:42 -0700199 // NOTE that we need to wait for LastCommunication to be equal or shorter that 5s
200 // as that means the core can talk to the adapters
201 // if voltctl can't read LastCommunication we skip this check
Joey Armstrong3d444c62022-11-26 21:42:20 -0500202
203 println("** ${iam}: Wait for adapter LastCommunication")
Joey Armstrong14a67a12022-11-28 12:28:23 -0500204 Integer countdown = 60 * 10
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400205 while (true) {
206 sleep 1
207 def adapters = getAdapters()
208 // Why are we not failing hard on this condition ?
209 // Adapters in an unknown state == testing: roll the dice
210 if (adapters == 'SKIP') { break }
Andrea Campanella45b8eb72021-09-28 10:50:01 +0200211
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400212 def state = getAdaptersState(adapters)
213 if (state == 'VALID') { break } // IFF
Andrea Campanella45b8eb72021-09-28 10:50:01 +0200214
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400215 // ----------------------------------------------------------
216 // Excessive timeout but unsure where startup time boundry is
217 // [TODO] profile for a baseline
218 // [TODO] groovy.transform.TimedInterrupt
219 // ----------------------------------------------------------
220 countdown -= 1
221 if (1 > countdown) {
222 throw new Exception('ERROR: Timed out waiting on adapter startup')
223 }
Matteo Scandolo28722ea2021-10-01 15:48:42 -0700224 }
Andrea Campanella45b8eb72021-09-28 10:50:01 +0200225
Joey Armstrongf0c76902022-11-28 17:14:45 -0500226 println("** ${iam}: Tearing down port forwarding")
Joey Armstronge93c3fa2023-09-11 09:34:24 -0400227 Map pkpfArgs =\
228 [
229 'banner' : true, // display banner for logging
230 'show_procs' : true, // display procs under consideration
231 'filler' : true // fix conditional trailing comma
232 ]
Joey Armstrong96158a92022-11-25 10:36:06 -0500233
Joey Armstronge93c3fa2023-09-11 09:34:24 -0400234 // [TODO] 'kubectl.*port-forward'
235 pkill_port_forward('port-forward', pkpfArgs)
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400236
237 leave('process')
Joey Armstrong3d444c62022-11-26 21:42:20 -0500238 return
Andrea Campanella45b8eb72021-09-28 10:50:01 +0200239}
Joey Armstrong3d444c62022-11-26 21:42:20 -0500240
241// -----------------------------------------------------------------------
242// -----------------------------------------------------------------------
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400243def call(Map config=[:])
Joey Armstrong3d444c62022-11-26 21:42:20 -0500244{
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400245 try {
246 enter('main')
247 process(config)
Joey Armstrong3d444c62022-11-26 21:42:20 -0500248 }
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400249 catch (Exception err) { // groovylint-disable-line CatchException
Joey Armstronge93c3fa2023-09-11 09:34:24 -0400250 String iam = getIam('process')
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400251 println("** ${iam}: EXCEPTION ${err}")
252 throw err
Joey Armstrong3d444c62022-11-26 21:42:20 -0500253 }
Joey Armstrong74ec08c2023-08-31 11:25:57 -0400254 finally {
255 leave('main')
Joey Armstrong3d444c62022-11-26 21:42:20 -0500256 }
257 return
258}
259
Joey Armstrongaf679da2023-01-31 14:22:41 -0500260// [EOF]