ee16ad0f7d42b395aa94ff95eeb1cef82a7bc593
[integration/test.git] / csit / libraries / Utils.robot
1 *** Settings ***
2 Documentation     General Utils library. This library has broad scope, it can be used by any robot system tests.
3 Library           SSHLibrary
4 Library           String
5 Library           DateTime
6 Library           Process
7 Library           ./UtilLibrary.py
8 Resource          KarafKeywords.robot
9 Variables         ../variables/Variables.py
10
11 *** Variables ***
12 # TODO: Introduce ${tree_size} and use instead of 1 in the next line.
13 ${start}          sudo mn --controller=remote,ip=${ODL_SYSTEM_IP} --topo tree,1 --switch ovsk,protocols=OpenFlow13
14
15 *** Keywords ***
16 Start Suite
17     [Arguments]    ${system}=${TOOLS_SYSTEM_IP}    ${user}=${TOOLS_SYSTEM_USER}    ${password}=${TOOLS_SYSTEM_PASSWORD}    ${prompt}=${DEFAULT_LINUX_PROMPT}    ${timeout}=30s
18     [Documentation]    Basic setup/cleanup work that can be done safely before any system
19     ...    is run.
20     Log    Start the test on the base edition
21     Clean Mininet System
22     ${mininet_conn_id}=    Open Connection    ${system}    prompt=${prompt}    timeout=${timeout}
23     Set Suite Variable    ${mininet_conn_id}
24     Flexible Mininet Login    user=${user}    password=${password}
25     Execute Command    sudo ovs-vsctl set-manager ptcp:6644
26     Write    ${start}
27     Read Until    mininet>
28
29 Start Mininet
30     [Arguments]    ${system}=${TOOLS_SYSTEM_IP}    ${cmd}=${start}    ${custom}=    ${user}=${TOOLS_SYSTEM_USER}    ${password}=${TOOLS_SYSTEM_PASSWORD}    ${prompt}=${DEFAULT_LINUX_PROMPT}
31     ...    ${prompt_timeout}=30s
32     [Documentation]    Basic setup to start mininet with custom topology
33     Log    Start the test on the base edition
34     Clean Mininet System
35     ${mininet_conn_id}=    Open Connection    ${system}    prompt=${prompt}    timeout=${prompt_timeout}
36     Set Suite Variable    ${mininet_conn_id}
37     Flexible Mininet Login    user=${user}    password=${password}
38     Put File    ${custom}
39     Write    ${cmd}
40     Read Until    mininet>
41     [Return]    ${mininet_conn_id}
42
43 Stop Mininet
44     [Arguments]    ${mininet_conn_id}    ${prompt}=${DEFAULT_LINUX_PROMPT}
45     [Documentation]    Basic setup to stop/clean mininet
46     Switch Connection    ${mininet_conn_id}
47     SSHLibrary.Write    exit
48     Read Until    ${prompt}
49     Close Connection
50
51 Stop Suite
52     [Arguments]    ${prompt}=${DEFAULT_LINUX_PROMPT}
53     [Documentation]    Cleanup/Shutdown work that should be done at the completion of all
54     ...    tests
55     Log    Stop the test on the base edition
56     Switch Connection    ${mininet_conn_id}
57     Read
58     Write    exit
59     Read Until    ${prompt}
60     Close Connection
61
62 Report_Failure_Due_To_Bug
63     [Arguments]    ${number}
64     [Documentation]    Report that a test failed due to a known Bugzilla bug whose
65     ...    number is provided as an argument.
66     ...    This must be used in the [Teardown] setting of the affected test
67     ...    or as the first line of the test if FastFail module is not being
68     ...    used. It reports the URL of the bug on console and also puts it
69     ...    into the Robot log file.
70     ${msg}=    BuiltIn.Set_Variable    This test fails due to https://bugs.opendaylight.org/show_bug.cgi?id=${number}
71     ${newline}=    BuiltIn.Evaluate    chr(10)
72     Run Keyword If    "${TEST STATUS}"=="FAIL"    BuiltIn.Set Test Message    ${msg}${newline}${newline}${TEST_MESSAGE}
73     Run Keyword If    "${TEST STATUS}"=="FAIL"    BuiltIn.Log    ${msg}
74
75 Ensure All Nodes Are In Response
76     [Arguments]    ${URI}    ${node_list}
77     [Documentation]    A GET is made to the supplied ${URI} and every item in the ${node_list}
78     ...    is verified to exist in the repsonse. This keyword currently implies that it's node
79     ...    specific but any list of strings can be given in ${node_list}. Refactoring of this
80     ...    to make it more generic should be done. (see keyword "Check For Elements At URI")
81     : FOR    ${node}    IN    @{node_list}
82     \    ${resp}    RequestsLibrary.Get Request    session    ${URI}
83     \    Should Be Equal As Strings    ${resp.status_code}    200
84     \    Should Contain    ${resp.content}    ${node}
85
86 Check Nodes Stats
87     [Arguments]    ${node}
88     [Documentation]    A GET on the /node/${node} API is made and specific flow stat
89     ...    strings are checked for existence.
90     ${resp}    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}/node/${node}
91     Should Be Equal As Strings    ${resp.status_code}    200
92     Should Contain    ${resp.content}    flow-capable-node-connector-statistics
93     Should Contain    ${resp.content}    flow-table-statistics
94
95 Check That Port Count Is Ok
96     [Arguments]    ${node}    ${count}
97     [Documentation]    A GET on the /port API is made and the specified port ${count} is
98     ...    verified. A more generic Keyword "Check For Specific Number Of Elements At URI"
99     ...    also does this work and further consolidation should be done.
100     ${resp}    RequestsLibrary.Get Request    session    ${REST_CONTEXT}/${CONTAINER}/port
101     Log    ${resp.content}
102     Should Be Equal As Strings    ${resp.status_code}    200
103     Should Contain X Times    ${resp.content}    ${node}    ${count}
104
105 Check For Specific Number Of Elements At URI
106     [Arguments]    ${uri}    ${element}    ${expected_count}
107     [Documentation]    A GET is made to the specified ${URI} and the specific count of a
108     ...    given element is done (as supplied by ${element} and ${expected_count})
109     ${resp}    RequestsLibrary.Get Request    session    ${uri}
110     Log    ${resp.content}
111     Should Be Equal As Strings    ${resp.status_code}    200
112     Should Contain X Times    ${resp.content}    ${element}    ${expected_count}
113
114 Check For Elements At URI
115     [Arguments]    ${uri}    ${elements}
116     [Documentation]    A GET is made at the supplied ${URI} and every item in the list of
117     ...    ${elements} is verified to exist in the response
118     ${resp}    RequestsLibrary.Get Request    session    ${uri}
119     Log    ${resp.content}
120     Should Be Equal As Strings    ${resp.status_code}    200
121     : FOR    ${i}    IN    @{elements}
122     \    Should Contain    ${resp.content}    ${i}
123
124 Check For Elements Not At URI
125     [Arguments]    ${uri}    ${elements}
126     [Documentation]    A GET is made at the supplied ${URI} and every item in the list of
127     ...    ${elements} is verified to NOT exist in the response
128     ${resp}    RequestsLibrary.Get Request    session    ${uri}
129     Log    ${resp.content}
130     Should Be Equal As Strings    ${resp.status_code}    200
131     : FOR    ${i}    IN    @{elements}
132     \    Should Not Contain    ${resp.content}    ${i}
133
134 Clean Mininet System
135     [Arguments]    ${system}=${TOOLS_SYSTEM_IP}
136     Run Command On Mininet    ${system}    sudo mn -c
137     Run Command On Mininet    ${system}    sudo ps -elf | egrep 'usr/local/bin/mn' | egrep python | awk '{print "sudo kill -9",$4}' | sh
138
139 Clean Up Ovs
140     [Arguments]    ${system}=${TOOLS_SYSTEM_IP}
141     [Documentation]    Cleans up the OVS instance and remove any existing common known bridges.
142     ${output}=    Run Command On Mininet    ${system}    sudo ovs-vsctl list-br
143     Log    ${output}
144     : FOR    ${i}    IN    ${output}
145     \    Run Command On Mininet    ${system}    sudo ovs-vsctl --if-exists del-br ${i}
146     Run Command On Mininet    ${system}    sudo ovs-vsctl del-manager
147
148 Extract Value From Content
149     [Arguments]    ${content}    ${index}    ${strip}=nostrip
150     [Documentation]    Will take the given response content and return the value at the given index as a string
151     ${value}=    Get Json Value    ${content}    ${index}
152     ${value}=    Convert To String    ${value}
153     ${value}=    Run Keyword If    '${strip}' == 'strip'    Strip Quotes    ${value}
154     [Return]    ${value}
155
156 Get Process ID Based On Regex On Remote System
157     [Arguments]    ${system}    ${regex_string_to_match_on}    ${user}=${TOOLS_SYSTEM_USER}    ${password}=${EMPTY}    ${prompt}=${DEFAULT_LINUX_PROMPT}    ${prompt_timeout}=30s
158     [Documentation]    Uses ps to find a process that matches the supplied regex. Returns the PID of that process
159     ...    The ${regex_string_to_match_on} should produce a unique process otherwise the PID returned may not be
160     ...    the expected PID
161     # doing the extra -v grep in this command to exclude the grep process itself from the output
162     ${cmd}=    Set Variable    ps -elf | grep -v grep | grep ${regex_string_to_match_on} | awk '{print $4}'
163     ${output}=    Run Command On Remote System    ${system}    ${cmd}    user=${user}    password=${password}    prompt=${prompt}
164     ...    prompt_timeout=${prompt_timeout}
165     # ${output} contains the system prompt and all we want is the value of the number
166     ${pid}=    Fetch From Left    ${output}    \r
167     # TODO: Get Process * keywords have perhaps non-standard default credentials.
168     # ...    Should there be * On Mininet and * On Controller specializations?
169     [Return]    ${pid}
170
171 Get Process Thread Count On Remote System
172     [Arguments]    ${system}    ${pid}    ${user}=${TOOLS_SYSTEM_USER}    ${password}=${EMPTY}    ${prompt}=${DEFAULT_LINUX_PROMPT}    ${prompt_timeout}=30s
173     [Documentation]    Executes the ps command to retrieve the lightweight process (aka thread) count.
174     ${cmd}=    Set Variable    ps --no-headers -o nlwp ${pid}
175     ${output}=    Run Command On Remote System    ${system}    ${cmd}    user=${user}    password=${password}    prompt=${prompt}
176     ...    prompt_timeout=${prompt_timeout}
177     # ${output} contains the system prompt and all we want is the value of the number
178     ${thread_count}=    Fetch From Left    ${output}    \r
179     [Return]    ${thread_count}
180
181 Strip Quotes
182     [Arguments]    ${string_to_strip}
183     [Documentation]    Will strip ALL quotes from given string and return the new string
184     ${string_to_return}=    Replace String    ${string_to_strip}    "    \    count=-1
185     [Return]    ${string_to_return}
186
187 Flexible SSH Login
188     [Arguments]    ${user}    ${password}=${EMPTY}    ${delay}=0.5s
189     [Documentation]    On active SSH session: if given non-empty password, do Login, else do Login With Public Key.
190     ${pwd_length} =    BuiltIn.Get Length    ${password}
191     # ${pwd_length} is guaranteed to be an integer, so we are safe to evaluate it as Python expression.
192     BuiltIn.Run Keyword And Return If    ${pwd_length} > 0    SSHLibrary.Login    ${user}    ${password}    delay=${delay}
193     BuiltIn.Run Keyword And Return    SSHLibrary.Login With Public Key    ${user}    ${USER_HOME}/.ssh/${SSH_KEY}    ${KEYFILE_PASS}    delay=${delay}
194
195 Flexible Mininet Login
196     [Arguments]    ${user}=${TOOLS_SYSTEM_USER}    ${password}=${TOOLS_SYSTEM_PASSWORD}    ${delay}=0.5s
197     [Documentation]    Call Flexible SSH Login, but with default values suitable for Mininet machine.
198     BuiltIn.Run Keyword And Return    Flexible SSH Login    user=${user}    password=${password}    delay=${delay}
199
200 Flexible Controller Login
201     [Arguments]    ${user}=${ODL_SYSTEM_USER}    ${password}=${ODL_SYSTEM_PASSWORD}    ${delay}=0.5s
202     [Documentation]    Call Flexible SSH Login, but with default values suitable for Controller machine.
203     BuiltIn.Run Keyword And Return    Flexible SSH Login    user=${user}    password=${password}    delay=${delay}
204
205 Run Command On Remote System
206     [Arguments]    ${system}    ${cmd}    ${user}=${DEFAULT_USER}    ${password}=${EMPTY}    ${prompt}=${DEFAULT_LINUX_PROMPT}    ${prompt_timeout}=${DEFAULT_TIMEOUT}
207     [Documentation]    Reduces the common work of running a command on a remote system to a single higher level
208     ...    robot keyword, taking care to log in with a public key and. The command given is written
209     ...    and the output returned. No test conditions are checked.
210     Log    Attempting to execute ${cmd} on ${system} by ${user} with ${keyfile_pass} and ${prompt}
211     ${conn_id}=    SSHLibrary.Open Connection    ${system}    prompt=${prompt}    timeout=${prompt_timeout}
212     Flexible SSH Login    ${user}    ${password}
213     ${stdout}    ${stderr}    SSHLibrary.Execute Command    ${cmd}    return_stderr=True
214     SSHLibrary.Close Connection
215     Log    ${stderr}
216     [Return]    ${stdout}
217
218 Write_Bare_Ctrl_C
219     [Documentation]    Construct ctrl+c character and SSH-write it (without endline) to the current SSH connection.
220     ...    Do not read anything yet.
221     ${ctrl_c}=    BuiltIn.Evaluate    chr(int(3))
222     SSHLibrary.Write_Bare    ${ctrl_c}
223
224 Write Bare Ctrl D
225     [Documentation]    Construct ctrl+d character and SSH-write it (without endline) to the current SSH connection.
226     ...    Do not read anything yet.
227     ${ctrl_d}=    BuiltIn.Evaluate    chr(int(4))
228     SSHLibrary.Write Bare    ${ctrl_d}
229
230 Run Command On Mininet
231     [Arguments]    ${system}=${TOOLS_SYSTEM_IP}    ${cmd}=echo    ${user}=${TOOLS_SYSTEM_USER}    ${password}=${TOOLS_SYSTEM_PASSWORD}    ${prompt}=${TOOLS_SYSTEM_PROMPT}
232     [Documentation]    Call Run Comand On Remote System, but with default values suitable for Mininet machine.
233     BuiltIn.Run Keyword And Return    Run Command On Remote System    ${system}    ${cmd}    ${user}    ${password}    prompt=${prompt}
234
235 Run Command On Controller
236     [Arguments]    ${system}=${ODL_SYSTEM_IP}    ${cmd}=echo    ${user}=${ODL_SYSTEM_USER}    ${password}=${ODL_SYSTEM_PASSWORD}    ${prompt}=${ODL_SYSTEM_PROMPT}
237     [Documentation]    Call Run Comand On Remote System, but with default values suitable for Controller machine.
238     BuiltIn.Run Keyword And Return    Run Command On Remote System    ${system}    ${cmd}    ${user}    ${password}    prompt=${prompt}
239
240 Verify File Exists On Remote System
241     [Arguments]    ${system}    ${file}    ${user}=${TOOLS_SYSTEM_USER}    ${password}=${TOOLS_SYSTEM_PASSWORD}    ${prompt}=${DEFAULT_LINUX_PROMPT}    ${prompt_timeout}=5s
242     [Documentation]    Will create connection with public key and will PASS if the given ${file} exists,
243     ...    otherwise will FAIL
244     ${conn_id}=    Open Connection    ${system}    prompt=${prompt}    timeout=${prompt_timeout}
245     Flexible SSH Login    ${user}    ${password}
246     SSHLibrary.File Should Exist    ${file}
247     Close Connection
248
249 Verify Controller Is Not Dead
250     [Arguments]    ${controller_ip}=${ODL_SYSTEM_IP}
251     [Documentation]    Will execute any tests to verify the controller is not dead. Some checks are
252     ...    Out Of Memory Execptions.
253     Check Karaf Log File Does Not Have Messages    ${controller_ip}    java.lang.OutOfMemoryError
254     # TODO: Should Verify Controller * keywords also accept user, password, prompt and karaf_log arguments?
255
256 Verify Controller Has No Null Pointer Exceptions
257     [Arguments]    ${controller_ip}=${ODL_SYSTEM_IP}
258     [Documentation]    Will execute any tests to verify the controller is not having any null pointer eceptions.
259     Check Karaf Log File Does Not Have Messages    ${controller_ip}    java.lang.NullPointerException
260
261 Get Epoch Time
262     [Arguments]    ${time}
263     [Documentation]    Get the Epoc time from MM/DD/YYYY HH:MM:SS
264     ${epoch_time}=    Convert Date    ${time}    epoch    exclude_milles=True    date_format=%m/%d/%Y %H:%M:%S
265     ${epoch_time}=    Convert To Integer    ${epoch_time}
266     [Return]    ${epoch_time}
267
268 Remove Space on String
269     [Arguments]    ${str}    ${count}=-1
270     [Documentation]    Remove the empty space from given string.count is optional,if its given
271     ...    that many occurence of space will be removed from left
272     ${x}=    Convert To String    ${str}
273     ${x}=    Replace String    ${str}    ${SPACE}    ${EMPTY}    count=${count}
274     [Return]    ${x}
275
276 Split Value from String
277     [Arguments]    ${str}    ${splitter}
278     [Documentation]    Split the String based on given splitter and return as list
279     @{x}=    Split String    ${str}    ${splitter}
280     [Return]    @{x}
281
282 Concatenate the String
283     [Arguments]    ${str1}    ${str2}
284     [Documentation]    Catenate the two non-string objects and return as String
285     ${str1}=    Convert to String    ${str1}
286     ${str2}=    Convert to String    ${str2}
287     ${output}=    Catenate    ${str1}    ${str2}
288     [Return]    ${output}
289
290 Post Elements To URI
291     [Arguments]    ${rest_uri}    ${data}    ${headers}=${headers}
292     [Documentation]    Perform a POST rest operation, using the URL and data provided
293     ${resp} =    RequestsLibrary.Post Request    session    ${rest_uri}    data=${data}    headers=${headers}
294     Should Be Equal As Strings    ${resp.status_code}    200
295
296 Remove All Elements At URI
297     [Arguments]    ${uri}
298     ${resp}    RequestsLibrary.Delete Request    session    ${uri}
299     Should Be Equal As Strings    ${resp.status_code}    200
300
301 Remove All Elements At URI And Verify
302     [Arguments]    ${uri}
303     ${resp}    RequestsLibrary.Delete Request    session    ${uri}
304     Should Be Equal As Strings    ${resp.status_code}    200
305     ${resp}    RequestsLibrary.Get Request    session    ${uri}
306     Should Be Equal As Strings    ${resp.status_code}    404
307
308 Add Elements To URI From File
309     [Arguments]    ${dest_uri}    ${data_file}    ${headers}=${headers}
310     ${body}    OperatingSystem.Get File    ${data_file}
311     ${resp}    RequestsLibrary.Put Request    session    ${dest_uri}    data=${body}    headers=${headers}
312     Should Be Equal As Strings    ${resp.status_code}    200
313
314 Post Elements To URI From File
315     [Arguments]    ${dest_uri}    ${data_file}    ${headers}=${headers}
316     ${body}    OperatingSystem.Get File    ${data_file}
317     ${resp}    RequestsLibrary.Post Request    session    ${dest_uri}    data=${body}    headers=${headers}
318     Should Be Equal As Strings    ${resp.status_code}    200
319
320 Run Process With Logging And Status Check
321     [Arguments]    @{proc_args}
322     [Documentation]    Execute an OS command, log STDOUT and STDERR output and check exit code to be 0
323     ${result}=    Run Process    @{proc_args}
324     Log    ${result.stdout}
325     Log    ${result.stderr}
326     Should Be Equal As Integers    ${result.rc}    0
327     [Return]    ${result}
328
329 Get Data From URI
330     [Arguments]    ${session}    ${uri}    ${headers}=${NONE}
331     [Documentation]    Issue a GET request and return the data obtained or on error log the error and fail.
332     ...    Issues a GET request for ${uri} in ${session} using headers from
333     ...    ${headers}. If the request returns a HTTP error, fails. Otherwise
334     ...    returns the data obtained by the request.
335     ${response}=    RequestsLibrary.Get Request    ${session}    ${uri}    ${headers}
336     Builtin.Return_From_Keyword_If    ${response.status_code} == 200    ${response.text}
337     Builtin.Log    ${response.text}
338     Builtin.Fail    The request failed with code ${response.status_code}
339
340 No Content From URI
341     [Arguments]    ${session}    ${uri}    ${headers}=${NONE}
342     [Documentation]    Issue a GET request and return on error 404 (No content) or will fail and log the content.
343     ...    Issues a GET request for ${uri} in ${session} using headers from
344     ...    ${headers}. If the request returns a HTTP error, fails. Otherwise
345     ...    returns the data obtained by the request.
346     ${response}=    RequestsLibrary.Get Request    ${session}    ${uri}    ${headers}
347     Builtin.Return_From_Keyword_If    ${response.status_code} == 404
348     Builtin.Log    ${response.text}
349     Builtin.Fail    The request failed with code ${response.status_code}
350
351 Get Index From List Of Dictionaries
352     [Arguments]    ${dictionary_list}    ${key}    ${value}
353     [Documentation]    Extract index for the dictionary in a list that contains a key-value pair. Returns -1 if key-value is not found.
354     ${length}=    Get Length    ${dictionary_list}
355     ${index}=    Set Variable    -1
356     : FOR    ${i}    IN RANGE    ${length}
357     \    ${dictionary}=    Get From List    ${dictionary_list}    ${i}
358     \    Run Keyword If    '&{dictionary}[${key}]' == '${value}'    Set Test Variable    ${index}    ${i}
359     [Return]    ${index}
360
361 Check Item Occurrence
362     [Arguments]    ${string}    ${dictionary_item_occurrence}
363     [Documentation]    Check string for occurrences of items expressed in a list of dictionaries {item=occurrences}. 0 occurences means item is not present.
364     : FOR    ${item}    IN    @{dictionary_item_occurrence}
365     \    Should Contain X Times    ${string}    ${item}    &{dictionary_item_occurrence}[${item}]
366
367 Post Log Check
368     [Arguments]    ${uri}    ${body}    ${status_code}=200
369     [Documentation]    Post body to ${uri}, log response content, and check status
370     ${resp}=    RequestsLibrary.Post Request    session    ${uri}    ${body}
371     Log    ${resp.content}
372     Should Be Equal As Strings    ${resp.status_code}    ${status_code}
373     [Return]    ${resp}