blob: e00d2906697b5b2cc5f1486c7aba4f06d6fcff07 [file] [log] [blame]
Jon Halla440e872016-03-31 15:15:50 -07001import json
Jon Hall41d39f12016-04-11 22:54:35 -07002import time
Jon Halle1a3b752015-07-22 13:02:46 -07003
Jon Hall41d39f12016-04-11 22:54:35 -07004class HA():
Jon Hall57b50432015-10-22 10:20:10 -07005
Jon Halla440e872016-03-31 15:15:50 -07006 def __init__( self ):
7 self.default = ''
Jon Hall57b50432015-10-22 10:20:10 -07008
Jon Halla440e872016-03-31 15:15:50 -07009 def consistentCheck( self ):
10 """
11 Checks that TestON counters are consistent across all nodes.
Jon Halle1a3b752015-07-22 13:02:46 -070012
Jon Halla440e872016-03-31 15:15:50 -070013 Returns the tuple (onosCounters, consistent)
Jon Hall41d39f12016-04-11 22:54:35 -070014 - onosCounters is the parsed json output of the counters command on
15 all nodes
16 - consistent is main.TRUE if all "TestON" counters are consitent across
17 all nodes or main.FALSE
Jon Halla440e872016-03-31 15:15:50 -070018 """
Jon Halle1a3b752015-07-22 13:02:46 -070019 try:
Jon Halla440e872016-03-31 15:15:50 -070020 # Get onos counters results
21 onosCountersRaw = []
22 threads = []
23 for i in main.activeNodes:
24 t = main.Thread( target=utilities.retry,
25 name="counters-" + str( i ),
26 args=[ main.CLIs[i].counters, [ None ] ],
27 kwargs= { 'sleep': 5, 'attempts': 5,
28 'randomTime': True } )
29 threads.append( t )
30 t.start()
31 for t in threads:
32 t.join()
33 onosCountersRaw.append( t.result )
34 onosCounters = []
35 for i in range( len( main.activeNodes ) ):
36 try:
37 onosCounters.append( json.loads( onosCountersRaw[i] ) )
38 except ( ValueError, TypeError ):
39 main.log.error( "Could not parse counters response from ONOS" +
40 str( main.activeNodes[i] + 1 ) )
41 main.log.warn( repr( onosCountersRaw[ i ] ) )
42 onosCounters.append( [] )
43
44 testCounters = {}
45 # make a list of all the "TestON-*" counters in ONOS
Jon Hall41d39f12016-04-11 22:54:35 -070046 # lookes like a dict whose keys are the name of the ONOS node and
47 # values are a list of the counters. I.E.
Jon Halla440e872016-03-31 15:15:50 -070048 # { "ONOS1": [ { "name":"TestON-Partitions","value":56} ]
49 # }
50 # NOTE: There is an assumtion that all nodes are active
51 # based on the above for loops
52 for controller in enumerate( onosCounters ):
53 for key, value in controller[1].iteritems():
54 if 'TestON' in key:
55 node = 'ONOS' + str( controller[0] + 1 )
56 try:
57 testCounters[node].append( { key: value } )
58 except KeyError:
59 testCounters[node] = [ { key: value } ]
60 # compare the counters on each node
61 firstV = testCounters.values()[0]
62 tmp = [ v == firstV for k, v in testCounters.iteritems() ]
63 if all( tmp ):
64 consistent = main.TRUE
65 else:
66 consistent = main.FALSE
67 main.log.error( "ONOS nodes have different values for counters:\n" +
68 testCounters )
69 return ( onosCounters, consistent )
70 except Exception:
71 main.log.exception( "" )
72 main.cleanup()
73 main.exit()
74
75 def counterCheck( self, counterName, counterValue ):
76 """
77 Checks that TestON counters are consistent across all nodes and that
78 specified counter is in ONOS with the given value
79 """
80 try:
81 correctResults = main.TRUE
82 # Get onos counters results and consistentCheck
83 onosCounters, consistent = self.consistentCheck()
84 # Check for correct values
85 for i in range( len( main.activeNodes ) ):
86 current = onosCounters[i]
87 onosValue = None
88 try:
89 onosValue = current.get( counterName )
Jon Hall41d39f12016-04-11 22:54:35 -070090 except AttributeError:
Jon Halla440e872016-03-31 15:15:50 -070091 node = str( main.activeNodes[i] + 1 )
Jon Hall41d39f12016-04-11 22:54:35 -070092 main.log.exception( "ONOS" + node + " counters result " +
93 "is not as expected" )
Jon Halla440e872016-03-31 15:15:50 -070094 correctResults = main.FALSE
95 if onosValue == counterValue:
96 main.log.info( counterName + " counter value is correct" )
97 else:
Jon Hall41d39f12016-04-11 22:54:35 -070098 main.log.error( counterName +
99 " counter value is incorrect," +
100 " expected value: " + str( counterValue ) +
101 " current value: " + str( onosValue ) )
Jon Halla440e872016-03-31 15:15:50 -0700102 correctResults = main.FALSE
103 return consistent and correctResults
104 except Exception:
105 main.log.exception( "" )
106 main.cleanup()
107 main.exit()
Jon Hall41d39f12016-04-11 22:54:35 -0700108
109 def consistentLeaderboards( self, nodes ):
110 TOPIC = 'org.onosproject.election'
111 # FIXME: use threads
112 #FIXME: should we retry outside the function?
113 for n in range( 5 ): # Retry in case election is still happening
114 leaderList = []
115 # Get all leaderboards
116 for cli in nodes:
117 leaderList.append( cli.specificLeaderCandidate( TOPIC ) )
118 # Compare leaderboards
119 result = all( i == leaderList[0] for i in leaderList ) and\
120 leaderList is not None
121 main.log.debug( leaderList )
122 main.log.warn( result )
123 if result:
124 return ( result, leaderList )
125 time.sleep(5) # TODO: paramerterize
126 main.log.error( "Inconsistent leaderboards:" + str( leaderList ) )
127 return ( result, leaderList )
128
129 def nodesCheck( self, nodes ):
130 nodesOutput = []
131 results = True
132 threads = []
133 for i in nodes:
134 t = main.Thread( target=main.CLIs[i].nodes,
135 name="nodes-" + str( i ),
136 args=[ ] )
137 threads.append( t )
138 t.start()
139
140 for t in threads:
141 t.join()
142 nodesOutput.append( t.result )
143 ips = [ main.nodes[node].ip_address for node in nodes ]
144 ips.sort()
145 for i in nodesOutput:
146 try:
147 current = json.loads( i )
148 activeIps = []
149 currentResult = False
150 for node in current:
151 if node['state'] == 'READY':
152 activeIps.append( node['ip'] )
153 activeIps.sort()
154 if ips == activeIps:
155 currentResult = True
156 except ( ValueError, TypeError ):
157 main.log.error( "Error parsing nodes output" )
158 main.log.warn( repr( i ) )
159 currentResult = False
160 results = results and currentResult
161 return results