2 Library RequestsLibrary
5 Library ClusterStateLibrary.py
9 ${smc_node} /org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore
10 ${jolokia_read} /jolokia/read/org.opendaylight.controller
13 Create Controller Index List
14 [Documentation] Reads number of controllers and returns a list with all controllers indexes.
15 ${controller_index_list} Create List
16 ${NUM_ODL_SYSTEM}= Convert to Integer ${NUM_ODL_SYSTEM}
17 : FOR ${i} IN RANGE ${NUM_ODL_SYSTEM}
18 \ Append To List ${controller_index_list} ${i+1}
19 [Return] ${controller_index_list}
21 Create Controller Sessions
22 [Documentation] Creates REST session to all controller instances.
23 ${NUM_ODL_SYSTEM}= Convert to Integer ${NUM_ODL_SYSTEM}
24 : FOR ${i} IN RANGE ${NUM_ODL_SYSTEM}
25 \ Log Create Session ${ODL_SYSTEM_${i+1}_IP}
26 \ Create Session controller${i+1} http://${ODL_SYSTEM_${i+1}_IP}:${RESTCONFPORT} auth=${AUTH}
28 Get Cluster Shard Status
29 [Arguments] ${controller_index_list} ${shard_type} ${shard}
30 [Documentation] Checks ${shard} status and returns Leader index and a list of Followers from a ${controller_index_list}.
31 ... ${shard_type} is either config or operational.
32 ${lenght}= Get Length ${controller_index_list}
33 Run Keyword If '${shard_type}' == 'config' Set Test Variable ${type} DistributedConfigDatastore
34 Run Keyword If '${shard_type}' == 'operational' Set Test Variable ${type} DistributedOperationalDatastore
35 Should Not Be Empty ${type} Wrong type, valid values are config and operational.
36 ${leader}= Set Variable 0
37 ${follower_list}= Create List
38 : FOR ${i} IN @{controller_index_list}
39 \ ${data}= Get Data From URI controller${i} ${jolokia_read}:Category=Shards,name=member-${i}-shard-${shard}-${shard_type},type=${type}
41 \ ${json}= To Json ${data}
42 \ ${status}= Get From Dictionary &{json}[value] RaftState
43 \ Log Controller ${ODL_SYSTEM_${i}_IP} is ${status} for shard ${shard}
44 \ Run Keyword If '${status}' == 'Leader' Set Test Variable ${leader} ${i}
45 \ Run Keyword If '${status}' == 'Follower' Append To List ${follower_list} ${i}
46 Should Not Be Equal ${leader} 0 No Leader elected in shard ${shard_type} ${shard}
47 Length Should Be ${follower_list} ${lenght-1} Not enough or too many Followers in shard ${shard_type} ${shard}
48 [Return] ${leader} ${follower_list}
50 Get Cluster Entity Owner Status
51 [Arguments] ${controller_index_list} ${device_type} ${device}
52 [Documentation] Checks Entity Owner status for a ${device} and returns owner index and list of candidates from a ${controller_index_list}.
53 ... ${device_type} is openflow, ovsdb, etc...
54 ${length}= Get Length ${controller_index_list}
55 ${candidates_list}= Create List
56 ${data}= Get Data From URI controller@{controller_index_list}[0] /restconf/operational/entity-owners:entity-owners
58 ${data}= Replace String ${data} /general-entity:entity[general-entity:name=' ${EMPTY}
59 ${clear_data}= Replace String ${data} '] ${EMPTY}
61 ${json}= To Json ${clear_data}
62 ${entity_type_list}= Get From Dictionary &{json}[entity-owners] entity-type
63 ${entity_type_index}= Get Index From List Of Dictionaries ${entity_type_list} type ${device_type}
64 Should Not Be Equal ${entity_type_index} -1 No Entity Owner found for ${device_type}
65 ${entity_list}= Get From Dictionary @{entity_type_list}[${entity_type_index}] entity
66 ${entity_index}= Get Index From List Of Dictionaries ${entity_list} id ${device}
67 Should Not Be Equal ${entity_index} -1 Device ${device} not found in Entity Owner ${device_type}
68 ${entity_owner}= Get From Dictionary @{entity_list}[${entity_index}] owner
69 Should Not Be Empty ${entity_owner} No owner found for ${device}
70 ${owner}= Replace String ${entity_owner} member- ${EMPTY}
71 ${owner}= Convert To Integer ${owner}
72 ${entity_candidates_list}= Get From Dictionary @{entity_list}[${entity_index}] candidate
73 ${list_length}= Get Length ${entity_candidates_list}
74 Should Be Equal ${list_length} ${length} Not enough or too many candidates for ${device}
75 : FOR ${entity_candidate} IN @{entity_candidates_list}
76 \ ${candidate}= Replace String &{entity_candidate}[name] member- ${EMPTY}
77 \ ${candidate}= Convert To Integer ${candidate}
78 \ Run Keyword If '${candidate}' != '${owner}' Append To List ${candidates_list} ${candidate}
79 [Return] ${owner} ${candidates_list}
81 Check Item Occurrence At URI In Cluster
82 [Arguments] ${controller_index_list} ${dictionary_item_occurrence} ${uri} ${headers}=${HEADERS}
83 [Documentation] Send a GET with the supplied ${uri} to all cluster instances in ${controller_index_list}
84 ... and check for occurrences of items expressed in a dictionary ${dictionary_item_occurrence}.
85 : FOR ${i} IN @{controller_index_list}
86 \ ${data} Get Data From URI controller${i} ${uri} ${headers}
88 \ Check Item Occurrence ${data} ${dictionary_item_occurrence}
90 Put And Check At URI In Cluster
91 [Arguments] ${controller_index_list} ${controller_index} ${uri} ${body} ${headers}=${HEADERS}
92 [Documentation] Send a PUT with the supplied ${uri} and ${body} to a ${controller_index}
93 ... and check the data is replicated in all instances in ${controller_index_list}.
94 ${expected_body}= To Json ${body}
95 ${resp} RequestsLibrary.Put Request controller${controller_index} ${uri} ${body} ${headers}
96 Should Be Equal As Strings ${resp.status_code} 200
97 : FOR ${i} IN @{controller_index_list}
98 \ ${data} Wait Until Keyword Succeeds 5s 1s Get Data From URI controller${i}
99 \ ... ${uri} ${headers}
101 \ ${received_body} To Json ${data}
102 \ Should Be Equal ${received_body} ${expected_body}
104 Delete And Check At URI In Cluster
105 [Arguments] ${controller_index_list} ${controller_index} ${uri} ${headers}=${HEADERS}
106 [Documentation] Send a DELETE with the supplied ${uri} to a ${controller_index}
107 ... and check the data is removed from all instances in ${controller_index_list}.
108 ${resp} RequestsLibrary.Delete Request controller${controller_index} ${uri} ${headers}
109 Should Be Equal As Strings ${resp.status_code} 200
110 : FOR ${i} IN @{controller_index_list}
111 \ Wait Until Keyword Succeeds 5s 1s No Content From URI controller${i} ${uri}
115 [Arguments] ${exclude_controller}=${EMPTY}
116 [Documentation] Creates a list of all controllers minus any excluded controller.
117 Log ${exclude_controller}
118 @{searchlist} Create List ${CONTROLLER} ${CONTROLLER1} ${CONTROLLER2}
119 Remove Values From List ${searchlist} ${exclude_controller}
121 [Return] ${searchlist}
123 Get Leader And Verify
124 [Arguments] ${shard_name} ${old_leader}=${EMPTY}
125 [Documentation] Returns the IP addr or hostname of the leader of the specified shard.
126 ... Controllers are specifed in the pybot command line.
127 ${searchlist} Get Controller List ${old_leader}
128 ${leader} GetLeader ${shard_name} ${3} ${3} ${1} ${RESTCONFPORT}
130 Should Not Be Equal As Strings ${leader} None
131 Run Keyword If '${old_leader}'!='${EMPTY}' Should Not Be Equal ${old_leader} ${leader}
135 [Arguments] ${shard_name}
136 [Documentation] No leader is elected in the car shard
137 ${leader} GetLeader ${shard_name} ${3} ${1} ${1} ${RESTCONFPORT}
138 ... ${CURRENT_CAR_LEADER}
139 Should Be Equal As Strings ${leader} None
142 [Arguments] ${shard_name} ${exclude_controller}=${EMPTY}
143 [Documentation] Returns the IP addresses or hostnames of all followers of the specified shard.
144 ${searchlist} Get Controller List ${exclude_controller}
145 ${followers} GetFollowers ${shard_name} ${3} ${3} ${1} ${RESTCONFPORT}
148 Should Not Be Empty ${followers}
149 [Return] ${followers}
151 Stop One Or More Controllers
152 [Arguments] @{controllers}
153 [Documentation] Give this keyword a scalar or list of controllers to be stopped.
154 ${cmd} = Set Variable ${KARAF_HOME}/bin/stop
155 : FOR ${ip} IN @{controllers}
156 \ Run Command On Remote System ${ip} ${cmd}
158 Kill One Or More Controllers
159 [Arguments] @{controllers}
160 [Documentation] Give this keyword a scalar or list of controllers to be stopped.
161 ${cmd} = Set Variable ps axf | grep karaf | grep -v grep | awk '{print \"kill -9 \" $1}' | sh
163 : FOR ${ip} IN @{controllers}
164 \ Run Command On Remote System ${ip} ${cmd}
166 Wait For Cluster Down
167 [Arguments] ${timeout} @{controllers}
168 [Documentation] Waits for one or more clustered controllers to be down.
169 : FOR ${ip} IN @{controllers}
170 \ ${status}= Run Keyword And Return Status Wait For Controller Down ${timeout} ${ip}
171 \ Exit For Loop If '${status}' == 'FAIL'
173 Wait For Controller Down
174 [Arguments] ${timeout} ${ip}
175 [Documentation] Waits for one controllers to be down.
176 Wait Until Keyword Succeeds ${timeout} 2s Controller Down Check ${ip}
178 Controller Down Check
180 [Documentation] Checks to see if a controller is down by verifying that the karaf process isn't present.
181 ${cmd} = Set Variable ps axf | grep karaf | grep -v grep | wc -l
182 ${response} Run Command On Remote System ${ip} ${cmd}
183 Log Number of controller instances running: ${response}
184 Should Start With ${response} 0 Controller process found or there may be extra instances of karaf running on the host machine.
186 Start One Or More Controllers
187 [Arguments] @{controllers}
188 [Documentation] Give this keyword a scalar or list of controllers to be started.
189 ${cmd} = Set Variable ${KARAF_HOME}/bin/start
190 : FOR ${ip} IN @{controllers}
191 \ Run Command On Remote System ${ip} ${cmd}
193 Wait For Cluster Sync
194 [Arguments] ${timeout} @{controllers}
195 [Documentation] Waits for one or more clustered controllers to report Sync Status as true.
196 : FOR ${ip} IN @{controllers}
197 \ ${status}= Run Keyword And Return Status Wait For Controller Sync ${timeout} ${ip}
198 \ Exit For Loop If '${status}' == 'FAIL'
200 Wait For Controller Sync
201 [Arguments] ${timeout} ${ip}
202 [Documentation] Waits for one controllers to report Sync Status as true.
203 Wait Until Keyword Succeeds ${timeout} 2s Controller Sync Status Should Be True ${ip}
205 Controller Sync Status Should Be True
207 [Documentation] Checks if Sync Status is true.
208 ${SyncStatus}= Get Controller Sync Status ${ip}
209 Should Be Equal ${SyncStatus} ${True}
211 Controller Sync Status Should Be False
213 [Documentation] Checks if Sync Status is false.
214 ${SyncStatus}= Get Controller Sync Status ${ip}
215 Should Be Equal ${SyncStatus} ${False}
217 Get Controller Sync Status
218 [Arguments] ${controller_ip}
219 [Documentation] Return Sync Status.
220 ${api} Set Variable /jolokia/read
221 Create_Session session http://${controller_ip}:${RESTCONFPORT}${api} headers=${HEADERS} auth=${AUTH}
222 ${resp}= RequestsLibrary.Get session ${smc_node}
225 ${json}= Set Variable ${resp.json()}
226 ${value}= Get From Dictionary ${json} value
228 ${SyncStatus}= Get From Dictionary ${value} SyncStatus
229 Log SyncSatus: ${SyncStatus}
230 [Return] ${SyncStatus}
232 Clean One Or More Journals
233 [Arguments] @{controllers}
234 [Documentation] Give this keyword a scalar or list of controllers on which to clean journals.
235 ${del_cmd} = Set Variable rm -rf ${KARAF_HOME}/journal
236 : FOR ${ip} IN @{controllers}
237 \ Run Command On Remote System ${ip} ${del_cmd}
239 Clean One Or More Snapshots
240 [Arguments] @{controllers}
241 [Documentation] Give this keyword a scalar or list of controllers on which to clean snapshots.
242 ${del_cmd} = Set Variable rm -rf ${KARAF_HOME}/snapshots
243 : FOR ${ip} IN @{controllers}
244 \ Run Command On Remote System ${ip} ${del_cmd}
246 Show Cluster Configuation Files
247 [Arguments] @{controllers}
248 [Documentation] Prints out the cluster configuration files for one or more controllers.
249 Log controllers: @{controllers}
250 ${cmd} = Set Variable cat ${KARAF_HOME}/configuration/initial/akka.conf
251 : FOR ${ip} IN @{controllers}
252 \ Run Command On Remote System ${ip} ${cmd}
253 ${cmd} = Set Variable cat ${KARAF_HOME}/configuration/initial/modules.conf
254 : FOR ${ip} IN @{controllers}
255 \ Run Command On Remote System ${ip} ${cmd}
256 ${cmd} = Set Variable cat ${KARAF_HOME}/configuration/initial/module-shards.conf
257 : FOR ${ip} IN @{controllers}
258 \ Run Command On Remote System ${ip} ${cmd}
259 ${cmd} = Set Variable cat ${KARAF_HOME}/configuration/initial/jolokia.xml
260 : FOR ${ip} IN @{controllers}
261 \ Run Command On Remote System ${ip} ${cmd}
262 ${cmd} = Set Variable cat ${KARAF_HOME}/etc/initial/org.apache.karaf.management.cfg
263 : FOR ${ip} IN @{controllers}
264 \ Run Command On Remote System ${ip} ${cmd}
265 ${cmd} = Set Variable cat ${KARAF_HOME}/etc/org.apache.karaf.features.cfg
266 : FOR ${ip} IN @{controllers}
267 \ Run Command On Remote System ${ip} ${cmd}
269 Isolate a Controller From Cluster
270 [Arguments] ${isolated controller} @{controllers}
271 [Documentation] Use IPTables to isolate one controller from the cluster.
272 ... On the isolated controller it blocks IP traffic to and from each of the other controllers.
273 : FOR ${controller} IN @{controllers}
274 \ ${other controller}= Evaluate "${isolated controller}" != "${controller}"
275 \ Run Keyword If ${other controller} Isolate One Controller From Another ${isolated controller} ${controller}
277 Rejoin a Controller To Cluster
278 [Arguments] ${isolated controller} @{controllers}
279 [Documentation] Use IPTables to rejoin one controller to the cluster.
280 ... On the isolated controller it unblocks IP traffic to and from each of the other controllers.
281 : FOR ${controller} IN @{controllers}
282 \ ${other controller}= Evaluate "${isolated controller}" != "${controller}"
283 \ Run Keyword If ${other controller} Rejoin One Controller To Another ${isolated controller} ${controller}
285 Isolate One Controller From Another
286 [Arguments] ${isolated controller} ${controller}
287 [Documentation] Inserts an IPTable rule to disconnect one controller from another controller in the cluster.
288 Modify IPTables ${isolated controller} ${controller} -I
290 Rejoin One Controller To Another
291 [Arguments] ${isolated controller} ${controller}
292 [Documentation] Deletes an IPTable rule, allowing one controller to reconnect to another controller in the cluster.
293 Modify IPTables ${isolated controller} ${controller} -D
296 [Arguments] ${isolated controller} ${controller} ${rule type}
297 [Documentation] Adds a rule, usually inserting or deleting an entry between two controllers.
298 ${base string} Set Variable sudo iptables ${rule type} OUTPUT -p all --source
299 ${cmd string} Catenate ${base string} ${isolated controller} --destination ${controller} -j DROP
300 Run Command On Remote System ${isolated controller} ${cmd string}
301 ${cmd string} Catenate ${base string} ${controller} --destination ${isolated controller} -j DROP
302 Run Command On Remote System ${isolated controller} ${cmd string}
303 ${cmd string} Set Variable sudo iptables -L -n
304 ${return string}= Run Command On Remote System ${isolated controller} ${cmd string}
306 Run Keyword If "${rule type}" == '-I' Should Match Regexp ${return string} [\s\S]*DROP *all *-- *${isolated controller} *${controller}[\s\S]*
307 Run Keyword If "${rule type}" == '-I' Should Match Regexp ${return string} [\s\S]*DROP *all *-- *${controller} *${isolated controller}[\s\S]*
309 Run Keyword If "${rule type}" == '-D' Should Match Regexp ${return string} (?![\s\S]*DROP *all *-- *${isolated controller} *${controller}[\s\S]*)
310 Run Keyword If "${rule type}" == '-D' Should Match Regexp ${return string} (?![\s\S]*DROP *all *-- *${controller} *${isolated controller}[\s\S]*)
312 Rejoin All Isolated Controllers
313 [Arguments] @{controllers}
314 [Documentation] Wipe all IPTables rules from all controllers, thus rejoining all controllers.
315 : FOR ${isolated controller} IN @{controllers}
316 \ Flush IPTables ${isolated controller}
319 [Arguments] ${isolated controller}
320 [Documentation] This keyword is generally not called from a test case but supports a complete wipe of all rules on
322 ${cmd string} Set Variable sudo iptables -v -F
323 ${return string}= Run Command On Remote System ${isolated controller} ${cmd string}
324 Log return: ${return string}
325 Should Contain ${return string} Flushing chain `INPUT'
326 Should Contain ${return string} Flushing chain `FORWARD'
327 Should Contain ${return string} Flushing chain `OUTPUT'