Initial works for OF cluster test
[integration/test.git] / csit / libraries / ClusterKeywords.robot
1 *** Settings ***
2 Library           RequestsLibrary
3 Library           Collections
4 Library           UtilLibrary.py
5 Library           ClusterStateLibrary.py
6 Resource          Utils.robot
7
8 *** Variables ***
9 ${smc_node}       /org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore
10 ${jolokia_read}    /jolokia/read/org.opendaylight.controller
11
12 *** Keywords ***
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}
20
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}
27
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}
40     \    Log    ${data}
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}
49
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
57     Log    ${data}
58     ${data}=    Replace String    ${data}    /general-entity:entity[general-entity:name='    ${EMPTY}
59     ${clear_data}=    Replace String    ${data}    ']    ${EMPTY}
60     Log    ${clear_data}
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}
80
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}
87     \    Log    ${data}
88     \    Check Item Occurrence    ${data}    ${dictionary_item_occurrence}
89
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}
100     \    Log    ${data}
101     \    ${received_body}    To Json    ${data}
102     \    Should Be Equal    ${received_body}    ${expected_body}
103
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}
112     \    ...    ${headers}
113
114 Get Controller List
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}
120     Log    ${searchlist}
121     [Return]    ${searchlist}
122
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}
129     ...    @{searchlist}
130     Should Not Be Equal As Strings    ${leader}    None
131     Run Keyword If    '${old_leader}'!='${EMPTY}'    Should Not Be Equal    ${old_leader}    ${leader}
132     [Return]    ${leader}
133
134 Expect No 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
140
141 Get All Followers
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}
146     ...    @{searchlist}
147     Log    ${followers}
148     Should Not Be Empty    ${followers}
149     [Return]    ${followers}
150
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}
157
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
162     log    ${cmd}
163     : FOR    ${ip}    IN    @{controllers}
164     \    Run Command On Remote System    ${ip}    ${cmd}
165
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'
172
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}
177
178 Controller Down Check
179     [Arguments]    ${ip}
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.
185
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}
192
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'
199
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}
204
205 Controller Sync Status Should Be True
206     [Arguments]    ${ip}
207     [Documentation]    Checks if Sync Status is true.
208     ${SyncStatus}=    Get Controller Sync Status    ${ip}
209     Should Be Equal    ${SyncStatus}    ${True}
210
211 Controller Sync Status Should Be False
212     [Arguments]    ${ip}
213     [Documentation]    Checks if Sync Status is false.
214     ${SyncStatus}=    Get Controller Sync Status    ${ip}
215     Should Be Equal    ${SyncStatus}    ${False}
216
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}
223     Log    ${resp.json()}
224     Log    ${resp.content}
225     ${json}=    Set Variable    ${resp.json()}
226     ${value}=    Get From Dictionary    ${json}    value
227     Log    value: ${value}
228     ${SyncStatus}=    Get From Dictionary    ${value}    SyncStatus
229     Log    SyncSatus: ${SyncStatus}
230     [Return]    ${SyncStatus}
231
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}
238
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}
245
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}
268
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}
276
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}
284
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
289
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
294
295 Modify IPTables
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}
305     #If inserting rules:
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]*
308     #If deleting rules:
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]*)
311
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}
317
318 Flush IPTables
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
321     ...    all contollers.
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'