blob: 6d8248902ff4e6d7dc7b3d0a78aecec30c1d6fb6 [file] [log] [blame]
Jon Hallca319892017-06-15 15:25:22 -07001"""
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07002Copyright 2017 Open Networking Foundation ( ONF )
Jon Hallca319892017-06-15 15:25:22 -07003
4Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
5the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
6or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
7
8 TestON is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070011 ( at your option ) any later version.
Jon Hallca319892017-06-15 15:25:22 -070012
13 TestON is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with TestON. If not, see <http://www.gnu.org/licenses/>.
20"""
Devin Lim3ebd5e72017-11-14 10:38:00 -080021import json
Jon Hallca319892017-06-15 15:25:22 -070022class Cluster():
23
24 def __str__( self ):
25 return self.name
Jon Hall4173b242017-09-12 17:04:38 -070026
Jon Hallca319892017-06-15 15:25:22 -070027 def __repr__( self ):
Jon Hallca319892017-06-15 15:25:22 -070028 controllers = []
Jon Hall3e6edb32018-08-21 16:20:30 -070029 runningNodes = self.getRunningNodes()
30 atomixNodes = []
Jon Hallca319892017-06-15 15:25:22 -070031 for ctrl in self.controllers:
Jon Hall3e6edb32018-08-21 16:20:30 -070032 controllers.append( "{%s:%s, %s - %s}" % ( ctrl.name,
33 ctrl.ipAddress,
34 "Configured" if ctrl in runningNodes else "Not Configured",
35 "Active" if ctrl.active else "Inactive" ) )
36 for node in self.atomixNodes:
37 atomixNodes.append( "{%s:%s}" % ( node.name, node.ipAddress ) )
38 return "%s[%s; Atomix Nodes:%s]" % ( self.name, ", ".join( controllers ), ", ".join( atomixNodes ) )
Jon Hallca319892017-06-15 15:25:22 -070039
Jon Hallca319892017-06-15 15:25:22 -070040 def __init__( self, ctrlList=[], name="Cluster" ):
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070041 """
Devin Lim142b5342017-07-20 15:22:39 -070042 controllers : All the nodes
43 runningNodes : Node that are specifically running from the test.
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070044 ie ) When the test is testing different number of nodes on each
Devin Lim142b5342017-07-20 15:22:39 -070045 run.
46 numCtrls : number of runningNodes
47 maxCtrls : number of controllers
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070048 """
Jon Hallca319892017-06-15 15:25:22 -070049 self.controllers = ctrlList
Devin Lim142b5342017-07-20 15:22:39 -070050 self.runningNodes = ctrlList
51 self.numCtrls = len( self.runningNodes )
52 self.maxCtrls = len( self.controllers )
Jon Hallca319892017-06-15 15:25:22 -070053 self.name = str( name )
Jon Hall3e6edb32018-08-21 16:20:30 -070054 self.atomixNodes = ctrlList
Jon Hallca319892017-06-15 15:25:22 -070055 self.iterator = iter( self.active() )
56
Jon Hall3e6edb32018-08-21 16:20:30 -070057 def fromNode( self, ctrlList ):
58 """
59 Helper function to get a specific list of controllers
60 Required Arguments:
61 * ctrlList - The list of controllers to return. This can be either an index or a keyword
62 Index | Keyword | List returned
63 0 | "all" | self.controllers
64 1 | "running" | self.runningNodes
65 2 | "active | self.active()
66
67 Throws a ValueError exception if ctrlList value is not recognized
68 """
69 # TODO: Add Atomix Nodes?
70 if isinstance( ctrlList, str ):
71 ctrlList = ctrlList.lower()
72 if ctrlList == 0 or ctrlList == "all":
73 return self.controllers
74 elif ctrlList == 1 or ctrlList == "running":
75 return self.runningNodes
76 elif ctrlList == 2 or ctrlList == "active":
77 return self.active()
78 else:
79 raise ValueError( "Unknown argument: {}".format( ctrlList ) )
80
Devin Lim142b5342017-07-20 15:22:39 -070081 def getIps( self, activeOnly=False, allNode=False ):
82 """
83 Description:
84 get the list of the ip. Default to get ips of running nodes.
85 Required:
86 * activeOnly - True for getting ips of active nodes
87 * allNode - True for getting ips of all nodes
88 Returns:
89 Retruns ips of active nodes if activeOnly is True.
90 Returns ips of all nodes if allNode is True.
91 """
Jon Hallca319892017-06-15 15:25:22 -070092 ips = []
Devin Lim142b5342017-07-20 15:22:39 -070093 if allNode:
Jon Hallca319892017-06-15 15:25:22 -070094 nodeList = self.controllers
Devin Lim142b5342017-07-20 15:22:39 -070095 else:
96 if activeOnly:
97 nodeList = self.active()
98 else:
99 nodeList = self.runningNodes
100
Jon Hallca319892017-06-15 15:25:22 -0700101 for ctrl in nodeList:
102 ips.append( ctrl.ipAddress )
Devin Lim142b5342017-07-20 15:22:39 -0700103
Jon Hallca319892017-06-15 15:25:22 -0700104 return ips
105
Jon Halla1e8e512018-05-11 13:30:57 -0700106 def clearActive( self ):
Jon Hallca319892017-06-15 15:25:22 -0700107 """
Devin Lim142b5342017-07-20 15:22:39 -0700108 Description:
Jon Halla1e8e512018-05-11 13:30:57 -0700109 Sets the activeness of each cluster node to be False
Jon Hallca319892017-06-15 15:25:22 -0700110 """
Jon Hallab611372018-02-21 15:26:05 -0800111 for ctrl in self.controllers:
Devin Lim142b5342017-07-20 15:22:39 -0700112 ctrl.active = False
113
114 def getRunningPos( self ):
115 """
116 Description:
117 get the position of the active running nodes.
118 Required:
119 Returns:
120 Retruns the list of the position of the active
121 running nodes.
122 """
123 return [ ctrl.pos for ctrl in self.runningNodes
124 if ctrl.active ]
125
126 def setRunningNode( self, numCtrls ):
127 """
128 Description:
129 Set running nodes of n number of nodes.
130 It will create new list of runningNodes.
131 If numCtrls is a list, it will add the nodes of the
132 list.
133 Required:
134 * numCtrls - number of nodes to be set.
135 Returns:
136 """
137 self.runningNodes = []
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700138 for i in numCtrls if isinstance( numCtrls, list ) else range( numCtrls ):
Devin Lim142b5342017-07-20 15:22:39 -0700139 self.runningNodes.append( self.controllers[ i ] )
140 self.numCtrls = len( numCtrls ) if isinstance( numCtrls, list ) else numCtrls
141
Jon Hall3e6edb32018-08-21 16:20:30 -0700142 def setAtomixNodes( self, nodes ):
143 """
144 Description:
145 Sets the list of Atomix nodes for the cluster
146 If nodes is a list, it will add the nodes of the list.
147 If nodes is an int, the function will set the Atomix nodes
148 to be the first n in the list of controllers.
149 Required:
150 * nodes - number of nodes to be set, or a list of nodes to set
151 Returns:
152 """
153 self.atomixNodes = []
154 for i in nodes if isinstance( nodes, list ) else range( nodes ):
155 self.atomixNodes.append( self.controllers[ i ] )
156
157 def getControllers( self, node=None ):
158 """
159 Description:
160 Get the list of all controllers in a cluster or a controller at an index in the list
161 Optional Arguments:
162 * node - position of the node to get from the list of controllers.
163 Returns:
164 Return a list of controllers in the cluster if node is None
165 if not, it will return the controller at the given index.
166 """
167 result = self.controllers
168 return result if node is None else result[ node % len( result ) ]
169
170 def getRunningNodes( self, node=None ):
171 """
172 Description:
173 Get the list of all controllers in a cluster that should be running or
174 a controller at an index in the list
175 Optional Arguments:
176 * node - position of the node to get from the list of controllers.
177 Returns:
178 Return a list of controllers in the cluster if node is None
179 if not, it will return the controller at the given index.
180 """
181 result = self.runningNodes
182 return result if node is None else result[ node % len( result ) ]
183
Devin Lim142b5342017-07-20 15:22:39 -0700184 def active( self, node=None ):
185 """
186 Description:
Jon Hall3e6edb32018-08-21 16:20:30 -0700187 Get the list of all active controllers in a cluster or
188 a controller at an index in the list
189 Optional Arguments:
190 * node - position of the node to get from the list of controllers.
Devin Lim142b5342017-07-20 15:22:39 -0700191 Returns:
Jon Hall3e6edb32018-08-21 16:20:30 -0700192 Return a list of controllers in the cluster if node is None
193 if not, it will return the controller at the given index.
Devin Lim142b5342017-07-20 15:22:39 -0700194 """
195 result = [ ctrl for ctrl in self.runningNodes
Jon Hallca319892017-06-15 15:25:22 -0700196 if ctrl.active ]
Devin Lim142b5342017-07-20 15:22:39 -0700197 return result if node is None else result[ node % len( result ) ]
Jon Hallca319892017-06-15 15:25:22 -0700198
199 def next( self ):
200 """
Jon Halla1e8e512018-05-11 13:30:57 -0700201 An iterator for the cluster's active controllers that
Jon Hallca319892017-06-15 15:25:22 -0700202 resets when there are no more elements.
203
204 Returns the next controller in the cluster
205 """
206 try:
Jon Halla1e8e512018-05-11 13:30:57 -0700207 node = self.iterator.next()
208 assert node.active
209 return node
210 except ( StopIteration, AssertionError ):
Jon Hallca319892017-06-15 15:25:22 -0700211 self.reset()
212 try:
213 return self.iterator.next()
214 except StopIteration:
215 raise RuntimeError( "There are no active nodes in the cluster" )
216
217 def reset( self ):
218 """
219 Resets the cluster iterator.
220
221 This should be used whenever a node's active state is changed
222 and is also used internally when the iterator has been exhausted.
223 """
224 self.iterator = iter( self.active() )
225
Jon Hall3e6edb32018-08-21 16:20:30 -0700226 def createCell( self, cellName, cellApps, mininetIp, useSSH, onosIps,
227 atomixIps, installMax=False ):
Jon Hallca319892017-06-15 15:25:22 -0700228 """
Devin Lim142b5342017-07-20 15:22:39 -0700229 Description:
230 create a new cell
231 Required:
232 * cellName - The name of the cell.
You Wang09b596b2018-01-10 10:42:38 -0800233 * cellApps - The ONOS apps string.
You Wanga0f6ff62018-01-11 15:46:30 -0800234 * mininetIp - Mininet IP address.
Devin Lim142b5342017-07-20 15:22:39 -0700235 * useSSH - True for using ssh when creating a cell
Jon Hall3e6edb32018-08-21 16:20:30 -0700236 * onosIps - ip( s ) of the ONOS node( s ).
237 * atomixIps - ip( s ) of the Atomix node( s ).
238
Devin Lim142b5342017-07-20 15:22:39 -0700239 Returns:
240 """
Devin Lime9f0ccf2017-08-11 17:25:12 -0700241 self.command( "createCellFile",
242 args=[ main.ONOSbench.ip_address,
Devin Lim40a19092017-08-15 14:54:22 -0700243 cellName,
You Wanga0f6ff62018-01-11 15:46:30 -0800244 mininetIp,
You Wang0d9f2c02018-08-10 14:56:32 -0700245 cellApps,
Jon Hall3e6edb32018-08-21 16:20:30 -0700246 onosIps,
247 atomixIps,
Devin Lim40a19092017-08-15 14:54:22 -0700248 main.ONOScell.karafUser,
249 useSSH ],
Devin Lime9f0ccf2017-08-11 17:25:12 -0700250 specificDriver=1,
Jon Hall3e6edb32018-08-21 16:20:30 -0700251 getFrom="all" if installMax else "running" )
Devin Lim40a19092017-08-15 14:54:22 -0700252
You Wangf9d95be2018-08-01 14:35:37 -0700253 def uninstallAtomix( self, uninstallMax ):
254 """
255 Description:
256 uninstalling atomix
257 Required:
258 * uninstallMax - True for uninstalling max number of nodes
259 False for uninstalling the current running nodes.
260 Returns:
261 Returns main.TRUE if it successfully uninstalled.
262 """
263 result = main.TRUE
264 uninstallResult = self.command( "atomixUninstall",
265 kwargs={ "nodeIp": "ipAddress" },
266 specificDriver=1,
Jon Hall3e6edb32018-08-21 16:20:30 -0700267 getFrom="all" if uninstallMax else "running",
You Wangf9d95be2018-08-01 14:35:37 -0700268 funcFromCtrl=True )
269 for uninstallR in uninstallResult:
270 result = result and uninstallR
271 return result
272
273 def uninstallOnos( self, uninstallMax ):
Devin Lim142b5342017-07-20 15:22:39 -0700274 """
275 Description:
276 uninstalling onos
277 Required:
278 * uninstallMax - True for uninstalling max number of nodes
279 False for uninstalling the current running nodes.
280 Returns:
281 Returns main.TRUE if it successfully uninstalled.
282 """
Devin Lim40a19092017-08-15 14:54:22 -0700283 result = main.TRUE
284 uninstallResult = self.command( "onosUninstall",
Jon Hall4173b242017-09-12 17:04:38 -0700285 kwargs={ "nodeIp": "ipAddress" },
Devin Lim40a19092017-08-15 14:54:22 -0700286 specificDriver=1,
Jon Hall3e6edb32018-08-21 16:20:30 -0700287 getFrom="all" if uninstallMax else "running",
Devin Lim40a19092017-08-15 14:54:22 -0700288 funcFromCtrl=True )
289 for uninstallR in uninstallResult:
290 result = result and uninstallR
291 return result
Devin Lim142b5342017-07-20 15:22:39 -0700292
Devin Lime9f0ccf2017-08-11 17:25:12 -0700293 def applyCell( self, cellName, installMax=False ):
Devin Lim142b5342017-07-20 15:22:39 -0700294 """
295 Description:
296 apply the cell with cellName. It will also verify the
297 cell.
298 Required:
299 * cellName - The name of the cell.
300 Returns:
301 Returns main.TRUE if it successfully set and verify cell.
302 """
Devin Lime9f0ccf2017-08-11 17:25:12 -0700303 setCellResult = self.command( "setCell",
Jon Hall4173b242017-09-12 17:04:38 -0700304 args=[ cellName ],
305 specificDriver=1,
Jon Hall3e6edb32018-08-21 16:20:30 -0700306 getFrom="all" )
307 benchCellResult = main.ONOSbench.setCell( cellName )
Devin Lime9f0ccf2017-08-11 17:25:12 -0700308 verifyResult = self.command( "verifyCell",
Jon Hall4173b242017-09-12 17:04:38 -0700309 specificDriver=1,
Jon Hall3e6edb32018-08-21 16:20:30 -0700310 getFrom="all" )
Devin Lime9f0ccf2017-08-11 17:25:12 -0700311 result = main.TRUE
312 for i in range( len( setCellResult ) ):
313 result = result and setCellResult[ i ] and verifyResult[ i ]
Jon Hall3e6edb32018-08-21 16:20:30 -0700314 result = result and benchCellResult
Devin Lime9f0ccf2017-08-11 17:25:12 -0700315 return result
Devin Lim142b5342017-07-20 15:22:39 -0700316
317 def checkService( self ):
318 """
319 Description:
320 Checking if the onos service is up. If not, it will
321 start the onos service manually.
322 Required:
323 Returns:
324 Returns main.TRUE if it successfully checked
325 """
Jon Hall3e6edb32018-08-21 16:20:30 -0700326 getFrom = "running"
Devin Lim142b5342017-07-20 15:22:39 -0700327 onosIsUp = main.TRUE
Devin Lim40a19092017-08-15 14:54:22 -0700328 onosUp = self.command( "isup",
329 args=[ "ipAddress" ],
330 specificDriver=1,
Jon Hall3e6edb32018-08-21 16:20:30 -0700331 getFrom=getFrom,
Devin Lim40a19092017-08-15 14:54:22 -0700332 funcFromCtrl=True )
Jon Hall3e6edb32018-08-21 16:20:30 -0700333 ctrlList = self.fromNode( getFrom )
Devin Lim40a19092017-08-15 14:54:22 -0700334 for i in range( len( onosUp ) ):
Jon Hall3e6edb32018-08-21 16:20:30 -0700335 ctrl = ctrlList[ i ]
Devin Lim40a19092017-08-15 14:54:22 -0700336 onosIsUp = onosIsUp and onosUp[ i ]
337 if onosUp[ i ] == main.TRUE:
Jon Hall9655dcb2018-02-02 11:19:06 -0800338 main.log.info( ctrl.name + " is up and ready" )
Devin Lim142b5342017-07-20 15:22:39 -0700339 else:
Jon Hall9655dcb2018-02-02 11:19:06 -0800340 main.log.warn( ctrl.name + " may not be up." )
341 return onosIsUp
Devin Lim142b5342017-07-20 15:22:39 -0700342
You Wangf9d95be2018-08-01 14:35:37 -0700343 def killAtomix( self, killMax, stopAtomix ):
344 """
345 Description:
346 killing atomix. It will either kill the current runningnodes or
347 max number of the nodes.
348 Required:
349 * killRemoveMax - The boolean that will decide either to kill
350 only running nodes ( False ) or max number of nodes ( True ).
351 * stopAtomix - If wish to atomix onos before killing it. True for
352 enable stop, False for disable stop.
353 Returns:
354 Returns main.TRUE if successfully killing it.
355 """
356 result = main.TRUE
357 killResult = self.command( "atomixKill",
358 args=[ "ipAddress" ],
359 specificDriver=1,
Jon Hall3e6edb32018-08-21 16:20:30 -0700360 getFrom="all" if killMax else "running",
You Wangf9d95be2018-08-01 14:35:37 -0700361 funcFromCtrl=True )
362 for i in range( len( killResult ) ):
363 result = result and killResult[ i ]
You Wangf9d95be2018-08-01 14:35:37 -0700364 return result
365
366 def killOnos( self, killMax, stopOnos ):
Devin Lim142b5342017-07-20 15:22:39 -0700367 """
368 Description:
369 killing the onos. It will either kill the current runningnodes or
370 max number of the nodes.
371 Required:
372 * killRemoveMax - The boolean that will decide either to kill
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700373 only running nodes ( False ) or max number of nodes ( True ).
Devin Lim142b5342017-07-20 15:22:39 -0700374 * stopOnos - If wish to stop onos before killing it. True for
375 enable stop , False for disable stop.
376 Returns:
377 Returns main.TRUE if successfully killing it.
Jon Hallca319892017-06-15 15:25:22 -0700378 """
Jon Hall3e6edb32018-08-21 16:20:30 -0700379 getFrom = "all" if killMax else "running"
Jon Hallca319892017-06-15 15:25:22 -0700380 result = main.TRUE
Devin Lim40a19092017-08-15 14:54:22 -0700381 killResult = self.command( "onosKill",
382 args=[ "ipAddress" ],
383 specificDriver=1,
Jon Hall3e6edb32018-08-21 16:20:30 -0700384 getFrom=getFrom,
Devin Lim40a19092017-08-15 14:54:22 -0700385 funcFromCtrl=True )
Jon Hall3e6edb32018-08-21 16:20:30 -0700386 ctrlList = self.fromNode( getFrom )
Jon Hall4173b242017-09-12 17:04:38 -0700387 for i in range( len( killResult ) ):
Devin Lim40a19092017-08-15 14:54:22 -0700388 result = result and killResult[ i ]
Jon Hall3e6edb32018-08-21 16:20:30 -0700389 ctrlList[ i ].active = False
Devin Lim142b5342017-07-20 15:22:39 -0700390 return result
391
392 def ssh( self ):
393 """
394 Description:
395 set up ssh to the onos
396 Required:
397 Returns:
398 Returns main.TRUE if it successfully setup the ssh to
399 the onos.
400 """
Devin Lim40a19092017-08-15 14:54:22 -0700401 result = main.TRUE
402 sshResult = self.command( "onosSecureSSH",
Jon Hall4173b242017-09-12 17:04:38 -0700403 kwargs={ "node": "ipAddress" },
Devin Lim40a19092017-08-15 14:54:22 -0700404 specificDriver=1,
Jon Hall3e6edb32018-08-21 16:20:30 -0700405 getFrom="running",
Devin Lim40a19092017-08-15 14:54:22 -0700406 funcFromCtrl=True )
407 for sshR in sshResult:
408 result = result and sshR
409 return result
Devin Lim142b5342017-07-20 15:22:39 -0700410
Jon Hall3e6edb32018-08-21 16:20:30 -0700411 def installAtomix( self, installParallel=True ):
You Wangf9d95be2018-08-01 14:35:37 -0700412 """
413 Description:
Jon Hall3e6edb32018-08-21 16:20:30 -0700414 Installing Atomix.
You Wangf9d95be2018-08-01 14:35:37 -0700415 Required:
You Wangf9d95be2018-08-01 14:35:37 -0700416 Returns:
417 Returns main.TRUE if it successfully installed
418 """
419 result = main.TRUE
420 threads = []
421 i = 0
Jon Hall3e6edb32018-08-21 16:20:30 -0700422 for ctrl in self.atomixNodes:
423 options = "-f"
You Wangf9d95be2018-08-01 14:35:37 -0700424 if installParallel:
425 t = main.Thread( target=ctrl.Bench.atomixInstall,
426 name="atomix-install-" + ctrl.name,
427 kwargs={ "node" : ctrl.ipAddress,
428 "options" : options } )
429 threads.append( t )
430 t.start()
431 else:
432 result = result and \
433 main.ONOSbench.atomixInstall( node=ctrl.ipAddress, options=options )
434 i += 1
435 if installParallel:
436 for t in threads:
437 t.join()
438 result = result and t.result
439 return result
440
441 def installOnos( self, installMax=True, installParallel=True ):
Devin Lim142b5342017-07-20 15:22:39 -0700442 """
443 Description:
444 Installing onos.
445 Required:
446 * installMax - True for installing max number of nodes
447 False for installing current running nodes only.
448 Returns:
449 Returns main.TRUE if it successfully installed
450 """
451 result = main.TRUE
452 threads = []
453 i = 0
454 for ctrl in self.controllers if installMax else self.runningNodes:
455 options = "-f"
456 if installMax and i >= self.numCtrls:
457 options = "-nf"
Devin Lime9f0ccf2017-08-11 17:25:12 -0700458 if installParallel:
Jon Hall4173b242017-09-12 17:04:38 -0700459 t = main.Thread( target=ctrl.Bench.onosInstall,
You Wangf9d95be2018-08-01 14:35:37 -0700460 name="onos-install-" + ctrl.name,
Jon Hall4173b242017-09-12 17:04:38 -0700461 kwargs={ "node" : ctrl.ipAddress,
462 "options" : options } )
Devin Lime9f0ccf2017-08-11 17:25:12 -0700463 threads.append( t )
464 t.start()
465 else:
466 result = result and \
Devin Lim142b5342017-07-20 15:22:39 -0700467 main.ONOSbench.onosInstall( node=ctrl.ipAddress, options=options )
Jon Halla6771b32018-01-26 16:07:28 -0800468 i += 1
Devin Lime9f0ccf2017-08-11 17:25:12 -0700469 if installParallel:
470 for t in threads:
471 t.join()
472 result = result and t.result
Jon Hallca319892017-06-15 15:25:22 -0700473 return result
474
475 def startCLIs( self ):
476 """
Devin Lim142b5342017-07-20 15:22:39 -0700477 Description:
478 starting Onos using onosCli driver
479 Required:
480 Returns:
481 Returns main.TRUE if it successfully started.
Jon Hallca319892017-06-15 15:25:22 -0700482 """
Jon Hall3e6edb32018-08-21 16:20:30 -0700483 getFrom = "running"
Devin Lim40a19092017-08-15 14:54:22 -0700484 result = main.TRUE
485 cliResults = self.command( "startOnosCli",
486 args=[ "ipAddress" ],
487 specificDriver=2,
Jon Hall3e6edb32018-08-21 16:20:30 -0700488 getFrom=getFrom,
Devin Lim40a19092017-08-15 14:54:22 -0700489 funcFromCtrl=True )
Jon Hall3e6edb32018-08-21 16:20:30 -0700490 ctrlList = self.fromNode( getFrom )
Jon Hall4173b242017-09-12 17:04:38 -0700491 for i in range( len( cliResults ) ):
Devin Lim40a19092017-08-15 14:54:22 -0700492 result = result and cliResults[ i ]
Jon Hall3e6edb32018-08-21 16:20:30 -0700493 ctrlList[ i ].active = True
Devin Lim40a19092017-08-15 14:54:22 -0700494 return result
Jon Hallca319892017-06-15 15:25:22 -0700495
Devin Lim3ebd5e72017-11-14 10:38:00 -0800496 def nodesCheck( self ):
You Wang0d9f2c02018-08-10 14:56:32 -0700497 """
498 Description:
499 Checking if all the onos nodes are in READY state
500 Required:
501 Returns:
502 Returns True if it successfully checked
503 """
Devin Lim3ebd5e72017-11-14 10:38:00 -0800504 results = True
505 nodesOutput = self.command( "nodes", specificDriver=2 )
506 ips = sorted( self.getIps( activeOnly=True ) )
507 for i in nodesOutput:
508 try:
509 current = json.loads( i )
510 activeIps = []
511 currentResult = False
512 for node in current:
513 if node[ 'state' ] == 'READY':
514 activeIps.append( node[ 'ip' ] )
515 activeIps.sort()
516 if ips == activeIps:
517 currentResult = True
Jon Hall3e6edb32018-08-21 16:20:30 -0700518 else:
519 main.log.error( "{} != {}".format( ips, activeIps ) )
Devin Lim3ebd5e72017-11-14 10:38:00 -0800520 except ( ValueError, TypeError ):
521 main.log.error( "Error parsing nodes output" )
522 main.log.warn( repr( i ) )
523 currentResult = False
524 results = results and currentResult
525 return results
526
You Wang0d9f2c02018-08-10 14:56:32 -0700527 def appsCheck( self, apps ):
528 """
529 Description:
530 Checking if all the applications are activated
531 Required:
532 apps: list of applications that are expected to be activated
533 Returns:
534 Returns True if it successfully checked
535 """
536 results = True
537 for app in apps:
538 states = self.command( "appStatus",
539 args=[ app ],
540 specificDriver=2 )
541 for i in range( len( states ) ):
542 ctrl = self.controllers[ i ]
543 if states[ i ] == "ACTIVE":
544 results = results and True
545 main.log.info( "{}: {} is activated".format( ctrl.name, app ) )
546 else:
547 results = False
548 main.log.warn( "{}: {} is in {} state".format( ctrl.name, app, states[ i ] ) )
549 return results
550
Devin Lim142b5342017-07-20 15:22:39 -0700551 def printResult( self, results, activeList, logLevel="debug" ):
552 """
553 Description:
554 Print the value of the list.
555 Required:
556 * results - list of the result
557 * activeList - list of the acitve nodes.
558 * logLevel - Type of log level you want it to be printed.
559 Returns:
560 """
561 f = getattr( main.log, logLevel )
Jon Hall4173b242017-09-12 17:04:38 -0700562 for i in range( len( results ) ):
563 f( activeList[ i ].name + "'s result : " + str( results[ i ] ) )
Devin Lim142b5342017-07-20 15:22:39 -0700564
565 def allTrueResultCheck( self, results, activeList ):
566 """
567 Description:
568 check if all the result has main.TRUE.
569 Required:
570 * results - list of the result
571 * activeList - list of the acitve nodes.
572 Returns:
573 Returns True if all == main.TRUE else
574 returns False
575 """
576 self.printResult( results, activeList )
577 return all( result == main.TRUE for result in results )
578
579 def notEmptyResultCheck( self, results, activeList ):
580 """
581 Description:
582 check if all the result has any contents
583 Required:
584 * results - list of the result
585 * activeList - list of the acitve nodes.
586 Returns:
587 Returns True if all the results has
588 something else returns False
589 """
590 self.printResult( results, activeList )
591 return all( result for result in results )
592
593 def identicalResultsCheck( self, results, activeList ):
594 """
595 Description:
596 check if all the results has same output.
597 Required:
598 * results - list of the result
599 * activeList - list of the acitve nodes.
600 Returns:
601 Returns True if all the results has
602 same result else returns False
603 """
604 self.printResult( results, activeList )
605 resultOne = results[ 0 ]
606 return all( resultOne == result for result in results )
607
Devin Lime9f0ccf2017-08-11 17:25:12 -0700608 def command( self, function, args=(), kwargs={}, returnBool=False,
Jon Hall3e6edb32018-08-21 16:20:30 -0700609 specificDriver=0, contentCheck=False, getFrom="active",
Devin Lim40a19092017-08-15 14:54:22 -0700610 funcFromCtrl=False ):
Devin Lim142b5342017-07-20 15:22:39 -0700611 """
612 Description:
613 execute some function of the active nodes.
614 Required:
615 * function - name of the function
616 * args - argument of the function
617 * kwargs - kwargs of the funciton
618 * returnBool - True if wish to check all the result has main.TRUE
619 * specificDriver - specific driver to execute the function. Since
620 some of the function can be used in different drivers, it is important
621 to specify which driver it will be executed from.
622 0 - any type of driver
623 1 - from bench
624 2 - from cli
625 3 - from rest
626 * contentCheck - If this is True, it will check if the result has some
627 contents.
Devin Lime9f0ccf2017-08-11 17:25:12 -0700628 * getFrom - from which nodes
Jon Hall3e6edb32018-08-21 16:20:30 -0700629 2 or "active" - active nodes
630 1 or "running" - current running nodes
631 0 or "all" - all nodes
Devin Lim40a19092017-08-15 14:54:22 -0700632 * funcFromCtrl - specific function of the args/kwargs
633 from each controller from the list of the controllers
Devin Lim142b5342017-07-20 15:22:39 -0700634 Returns:
635 Returns results if not returnBool and not contentCheck
636 Returns checkTruthValue of the result if returnBool
637 Returns resultContent of the result if contentCheck
638 """
Jon Hallca319892017-06-15 15:25:22 -0700639 threads = []
Devin Lim142b5342017-07-20 15:22:39 -0700640 drivers = [ None, "Bench", "CLI", "REST" ]
Jon Hallca319892017-06-15 15:25:22 -0700641 results = []
Jon Hall3e6edb32018-08-21 16:20:30 -0700642 for ctrl in self.fromNode( getFrom ):
Devin Lim142b5342017-07-20 15:22:39 -0700643 try:
Devin Lim40a19092017-08-15 14:54:22 -0700644 funcArgs = []
645 funcKwargs = {}
Devin Lim142b5342017-07-20 15:22:39 -0700646 f = getattr( ( ctrl if not specificDriver else
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700647 getattr( ctrl, drivers[ specificDriver ] ) ), function )
Devin Lim40a19092017-08-15 14:54:22 -0700648 if funcFromCtrl:
649 if args:
650 for i in range( len( args ) ):
651 funcArgs.append( getattr( ctrl, args[ i ] ) )
652 if kwargs:
653 for k in kwargs:
Jon Hall4173b242017-09-12 17:04:38 -0700654 funcKwargs.update( { k: getattr( ctrl, kwargs[ k ] ) } )
Devin Lim142b5342017-07-20 15:22:39 -0700655 except AttributeError:
656 main.log.error( "Function " + function + " not found. Exiting the Test." )
Devin Lim44075962017-08-11 10:56:37 -0700657 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700658 t = main.Thread( target=f,
659 name=function + "-" + ctrl.name,
Devin Lim40a19092017-08-15 14:54:22 -0700660 args=funcArgs if funcFromCtrl else args,
661 kwargs=funcKwargs if funcFromCtrl else kwargs )
Jon Hallca319892017-06-15 15:25:22 -0700662 threads.append( t )
663 t.start()
664
665 for t in threads:
666 t.join()
667 results.append( t.result )
Devin Lim142b5342017-07-20 15:22:39 -0700668 if returnBool:
Jon Hall3e6edb32018-08-21 16:20:30 -0700669 return self.allTrueResultCheck( results, self.fromNode( getFrom ) )
Devin Lim142b5342017-07-20 15:22:39 -0700670 elif contentCheck:
Jon Hall3e6edb32018-08-21 16:20:30 -0700671 return self.notEmptyResultCheck( results, self.fromNode( getFrom ) )
Jon Hall4173b242017-09-12 17:04:38 -0700672 return results
673
674 def checkPartitionSize( self, segmentSize='64', units='M', multiplier='3' ):
675 # max segment size in bytes: 1024 * 1024 * 64
676 # multiplier is somewhat arbitrary, but the idea is the logs would have
677 # been compacted before this many segments are written
678
679 maxSize = float( segmentSize ) * float( multiplier )
680 ret = True
681 for n in self.runningNodes:
Jon Hall5d5876e2017-11-30 09:33:16 -0800682 # Partition logs
Jon Halld81e0162018-08-13 12:06:13 -0700683 ret = ret and n.server.folderSize( "/opt/atomix/data/raft/partitions/*/*.log",
Jon Hall4173b242017-09-12 17:04:38 -0700684 size=maxSize, unit=units, ignoreRoot=False )
685 return ret