Add more robust wait for flow stats
[integration/test.git] / csit / libraries / FlowLib.robot
1 *** Settings ***
2 Documentation     Keywords used to create/modify flow objects. The object is defined in the
3 ...               corresponding FlowLib.py library and contains pertinent fields and methods (e.g.,
4 ...               cookie and barrier fields, string formatted xml that can be used to push to
5 ...               controller)
6 Library           ./FlowLib.py
7 Library           XML
8 Library           RequestsLibrary
9 Variables         ../variables/Variables.py
10
11 *** Variables ***
12
13 *** Keywords ***
14 Check Flow Stats Are Available
15     [Arguments]    ${node_id}    ${flows}
16     [Documentation]    A GET on the /node/${node_id} inventory API is made and flow stats string is checked for existence.
17     ${resp}    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}/node/${node_id}/table/2
18     Log    ${resp.content}
19     Should Be Equal As Strings    ${resp.status_code}    200
20     Should Contain X Times    ${resp.content}    packet-count    ${flows}
21
22 Create Inventory Flow
23     [Documentation]    Calls FlowLib.Make_Inventory_Flow function and initializes and sanitizes
24     ...    the basic flow elements that can be given to flow:inventory
25     ${flow}=    Make Inventory Flow
26     [Return]    ${flow}
27
28 Create Service Flow
29     [Documentation]    Used for creating an object that will use an XML format that
30     ...    can be given to flow:service.
31     ${flow}=    Make Service Flow
32     [Return]    ${flow}
33
34 Set "${flow}" "${property}" With "${property_val}"
35     [Documentation]    Embedded variables to make higher level keywords more readable.
36     ...    There are some cases where the python attribute uses an underscore,
37     ...    but a hyphen needs to be used. This seems inconsistent, and may need
38     ...    to be looked at from the openflow plugin perspective.
39     ...
40     ...    At this point, this library will remove the element ${property} from the
41     ...    xml representation of the flow and reset with the given value. \ It's not
42     ...    possible, yet, to have multiple elements with the same name. \ That will
43     ...    likely be needed in the future.
44     ${property}    Run Keyword If    "table_id" != "${property}" and "cookie_mask" != "${property}"    Replace String    ${property}    _    -
45     ...    ELSE    Set Variable    ${property}
46     Remove Flow XML Element    ${flow}    ${property}
47     Add Flow XML Element    ${flow}    ${property}    ${property_val}
48     Set Flow Field    ${flow}    ${property}    ${property_val}
49     [Return]    ${flow}
50
51 Set Flow Action
52     [Arguments]    ${flow}    ${instruction_order}    ${action_order}    ${action}    ${action_val}=${EMPTY}
53     [Documentation]    Will remove the instruction element first, then add the proper xml structure
54     ...    to implement the action as given in the arguments
55     ##For the case that any of the instruction/apply-actions/action elements are not there we need to add them'
56     Remove Flow XML Element    ${flow}    instruction
57     Add Flow XML Element    ${flow}    instruction    ${EMPTY}    instructions
58     Add Flow XML Element    ${flow}    order    ${instruction_order}    instructions/instruction
59     Add Flow XML Element    ${flow}    apply-actions    ${EMPTY}    instructions/instruction
60     Add Flow XML Element    ${flow}    action    ${EMPTY}    instructions/instruction/apply-actions
61     Add Flow XML Element    ${flow}    order    ${action_order}    instructions/instruction/apply-actions/action
62     Add Flow XML Element    ${flow}    ${action}    ${action_val}    instructions/instruction/apply-actions/action
63     [Return]    ${flow}
64
65 Set Flow Output Action
66     [Arguments]    ${flow}    ${instruction_order}    ${action_order}    ${output_port}
67     Set Flow Action    ${flow}    ${instruction_order}    ${action_order}    output-action
68     Add Flow XML Element    ${flow}    output-node-connector    ${output_port}    instructions/instruction/apply-actions/action/output-action
69     [Return]    ${flow}
70
71 Set Flow Ethernet Match
72     [Arguments]    ${flow}    ${match_value_dict}
73     [Documentation]    Specific keyword for adding an ethernet match rules where the elements are given
74     ...    in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any
75     ...    existing ethernet-match elements from the flow before adding
76     Clear Flow Matches    ${flow}    match/ethernet-match
77     Add Flow XML Element    ${flow}    ethernet-match    ${EMPTY}    match
78     ${type}=    Get From Dictionary    ${match_value_dict}    type
79     Add Flow XML Element    ${flow}    ethernet-type    ${EMPTY}    match/ethernet-match
80     Add Flow XML Element    ${flow}    type    ${type}    match/ethernet-match/ethernet-type
81     ${src}=    Get From Dictionary    ${match_value_dict}    source
82     Add Flow XML Element    ${flow}    ethernet-source    ${EMPTY}    match/ethernet-match
83     Add Flow XML Element    ${flow}    address    ${src}    match/ethernet-match/ethernet-source
84     ${dst}=    Get From Dictionary    ${match_value_dict}    destination
85     Add Flow XML Element    ${flow}    ethernet-destination    ${EMPTY}    match/ethernet-match
86     Add Flow XML Element    ${flow}    address    ${dst}    match/ethernet-match/ethernet-destination
87     [Return]    ${flow}
88
89 Set Flow IPv4 Match
90     [Arguments]    ${flow}    ${match_value_dict}
91     [Documentation]    Specific keyword for adding an ipv4 match rules where the elements are given
92     ...    in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any
93     ...    existing ipv4 match elements from the flow before adding
94     Clear Flow Matches    ${flow}    match/ipv4-source
95     Clear Flow Matches    ${flow}    match/ipv4-destination
96     ${src}=    Get From Dictionary    ${match_value_dict}    source
97     Add Flow XML Element    ${flow}    ipv4-source    ${src}    match
98     ${dst}=    Get From Dictionary    ${match_value_dict}    destination
99     Add Flow XML Element    ${flow}    ipv4-destination    ${dst}    match
100     [Return]    ${flow}
101
102 Clear Flow Actions
103     [Arguments]    ${flow}
104     [Documentation]    Will clean out any existing flow actions in the given ${flow} object
105     Remove Flow XML Element    ${flow}    instructions/instruction
106     [Return]    ${flow}
107
108 Clear Flow Matches
109     [Arguments]    ${flow}    ${match_element}
110     [Documentation]    Will clean out any existing flow matches in the given ${flow} object
111     Remove Flow XML Element    ${flow}    match/${match_element}
112     [Return]    ${flow}
113
114 Set Flow XML Element Attribute
115     [Arguments]    ${flow}    ${element}    ${id}    ${value}
116     [Documentation]    Will set the given id/value pair to the given to the element provided
117     ...    and make the proper changes to the ${flow} object also provided.
118     ${flow_xml}=    Parse XML    ${flow.xml}
119     Set Element Attribute    ${flow_xml}    ${id}    ${value}    xpath=${element}
120     ${xml_string}=    Element To String    ${flow_xml}
121     Set Flow Field    ${flow}    xml    ${xml_string}
122     Log    ${flow.xml}
123     [Return]    ${flow}
124
125 Add Flow XML Element
126     [Arguments]    ${flow}    ${element}    ${element_val}=${EMPTY}    ${xpath}=.
127     [Documentation]    Will modify the current xml representation of the ${flow} object to contain
128     ...    the given ${element} at the given ${xpath}. If the ${element} uses a value, that can be
129     ...    passed eith the ${element_val} which defaults to ${EMPTY} if not used. NOTE: since there
130     ...    are two default parameters to this keyword, if you have an ${xpath} to use, but no ${element_val}
131     ...    you will still need to pass ${EMPTY} when invoking so that ${xpath} will end up at the right
132     ...    location in the parameter list
133     ${flow_xml}=    Parse XML    ${flow.xml}
134     Add Element    ${flow_xml}    <${element}>${element_val}</${element}>    xpath=${xpath}
135     ${xml_string}=    Element To String    ${flow_xml}
136     Set Flow Field    ${flow}    xml    ${xml_string}
137     Log    ${flow.xml}
138     [Return]    ${flow}
139
140 Remove Flow XML Element
141     [Arguments]    ${flow}    ${element_xpath}
142     [Documentation]    Removes the element at the given ${element_xpath} within the given ${flow}
143     ...    object. The ${flow} object's xml representation will be updated to reflect this removal.
144     ${flow_xml}=    Parse XML    ${flow.xml}
145     Run Keyword And Ignore Error    Remove Elements    ${flow_xml}    xpath=${element_xpath}
146     ${xml_string}=    Element To String    ${flow_xml}
147     Set Flow Field    ${flow}    xml    ${xml_string}
148     [Return]    ${flow}
149
150 Add Flow To Controller And Verify
151     [Arguments]    ${flow_body}    ${node_id}    ${table_id}    ${flow_id}
152     [Documentation]    Push flow through REST-API and verify in data-store
153     ${resp}    RequestsLibrary.Put Request    session    ${REST_CON}/node/${node_id}/table/${table_id}/flow/${flow_id}    headers=${HEADERS_XML}    data=${flow_body}
154     Log    ${resp.content}
155     Should Be Equal As Strings    ${resp.status_code}    200
156     ${resp}    RequestsLibrary.Get Request    session    ${REST_CON}/node/${node_id}/table/${table_id}/flow/${flow_id}    headers=${ACCEPT_XML}
157     Log    ${resp.content}
158     Should Be Equal As Strings    ${resp.status_code}    200
159     compare xml    ${flow_body}    ${resp.content}
160
161 Verify Flow On Mininet Switch
162     [Arguments]    ${flow_elements}
163     [Documentation]    Checking flow on switch
164     sleep    1
165     write    dpctl dump-flows -O OpenFlow13
166     ${switchoutput}    Read Until    >
167     : FOR    ${flowElement}    IN    @{flow_elements}
168     \    should Contain    ${switchoutput}    ${flowElement}
169
170 Remove Flow From Controller And Verify
171     [Arguments]    ${flow_body}    ${node_id}    ${table_id}    ${flow_id}
172     [Documentation]    Remove flow
173     ${resp}    RequestsLibrary.Delete Request    session    ${REST_CON}/node/${node_id}/table/${table_id}/flow/${flow_id}
174     Log    ${resp.content}
175     Should Be Equal As Strings    ${resp.status_code}    200
176     ${resp}    RequestsLibrary.Get Request    session    ${REST_CON}/node/${node_id}/table/${table_id}
177     Log    ${resp.content}
178     Should Not Contain    ${resp.content}    ${flow_id}
179
180 Verify Flow Does Not Exist On Mininet Switch
181     [Arguments]    ${flow_elements}
182     [Documentation]    Checking flow on switch is removed
183     sleep    1
184     write    dpctl dump-flows -O OpenFlow13
185     ${switchoutput}    Read Until    >
186     : FOR    ${flowElement}    IN    @{flow_elements}
187     \    should Not Contain    ${switchoutput}    ${flowElement}
188
189 Remove Default Flows
190     [Arguments]    ${node_id}
191     [Documentation]    Removes any flows considered "default". one such flow is
192     ...    to forward all traffic to the CONTROLLER with priority 0 at flow-table 0
193     ...    If/When others are implemented this keyword can be updated to include those.
194     ${flow}=    Make Service Flow
195     Set "${flow}" "priority" With "0"
196     Set "${flow}" "flow-table" With "0"
197     Add Flow XML Element    ${flow}    node    /inv:nodes/inv:node[inv:id="${node_id}"]
198     Set Flow XML Element Attribute    ${flow}    node    xmlns:inv    urn:opendaylight:inventory
199     Log    Flow XML is ${flow.xml}
200     write    dpctl dump-flows -O OpenFlow13
201     ${switchoutput}    Read Until    >
202     ${headers}=    Create Dictionary    Content-Type=application/yang.data+xml
203     ${resp}    RequestsLibrary.Post Request    session    restconf/operations/sal-flow:remove-flow    data=${flow.xml}    headers=${headers}
204     Log    ${resp.content}
205     Should Be Equal As Strings    ${resp.status_code}    200
206     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}
207     Log    ${resp.content}
208     Should Not Contain    ${resp.content}    "output-node-connector": "CONTROLLER",
209     ${strings_to_check_for}=    Create List    CONTROLLER
210     Verify Flow Does Not Exist On Mininet Switch    ${strings_to_check_for}
211
212 Create Flow Variables For Suite From XML File
213     [Arguments]    ${file}
214     [Documentation]    Given the flow XML ${file}, it will create several suite wide variables
215     ${data}=    OperatingSystem.Get File    ${file}
216     ${xmlroot}=    Parse Xml    ${file}
217     ${table_id}=    Get Element Text    ${xmlroot}    table_id
218     ${flow_id}=    Get Element Text    ${xmlroot}    id
219     ${flow_priority}=    Get Element Text    ${xmlroot}    priority
220     ${upddata}=    Get Data For Flow Put Update    ${data}
221     Set Suite Variable    ${table_id}
222     Set Suite Variable    ${flow_id}
223     Set Suite Variable    ${flow_priority}
224     Set Suite Variable    ${data}
225     Set Suite Variable    ${upddata}
226     Set Suite Variable    ${xmlroot}
227
228 Check Datastore Presence
229     [Arguments]    ${fname}    ${reqconfpres}    ${reqoperpres}    ${upd}
230     [Documentation]    Checks if flow is properly existing or not existing in the config and operational
231     ...    datastores, based on the variables ${reqconfpres} and ${reqoperpres}
232     Create Flow Variables For Suite From XML File    ${XmlsDir}/${fname}
233     # Note:    ${upddata} and ${data} are suite variables set by the keyword above.
234     ${det}=    Set Variable If    ${upd}==${True}    ${upddata}    ${data}
235     Check Config Flow    ${reqconfpres}    ${det}
236     Check Operational Flow    ${reqoperpres}    ${det}
237
238 Flow Presence In Config Store
239     [Arguments]    ${expvalue}
240     [Documentation]    Checks the config store for given flow. Returns True if present, otherwise returns False
241     ...    This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx}
242     ${headers}=    Create Dictionary    Accept=application/xml
243     ${resp}=    RequestsLibrary.Get Request    session    ${CONFIG_NODES_API}/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id}    headers=${headers}
244     Log    ${resp}
245     Log    ${resp.content}
246     Return From Keyword If    ${resp.status_code}!=200    ${False}    ${EMPTY}
247     ${pres}    ${msg}=    Is Flow Configured    ${expvalue}    ${resp.content}
248     Run Keyword If    '''${msg}'''!='${EMPTY}'    Log    ${msg}
249     Return From Keyword    ${pres}    ${msg}
250
251 Flow Presence In Operational Store
252     [Arguments]    ${expvalue}
253     [Documentation]    Checks the operational store for given flow. Returns True if present, otherwise returns False
254     ...    This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx}
255     ${headers}=    Create Dictionary    Accept=application/xml
256     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}/node/openflow:${switch_idx}/table/${table_id}    headers=${headers}
257     Log    ${resp}
258     Log    ${resp.content}
259     Return From Keyword If    ${resp.status_code}!=200    ${False}    ${EMPTY}
260     ${pres}    ${msg}=    Is Flow Operational2    ${expvalue}    ${resp.content}
261     Run Keyword If    '''${msg}'''!='${EMPTY}'    Log    ${msg}
262     Return From Keyword    ${pres}    ${msg}
263
264 Get Presence Failure Message
265     [Arguments]    ${ds}    ${expected}    ${presence}    ${diffmsg}
266     [Documentation]    Utility keyword to help manipulate mesage strings that may be used later to PASS or FAIL with
267     Return From Keyword If    '''${diffmsg}'''!='${EMPTY}'    Flow found in ${ds} data store but: ${diffmsg}
268     ${msgf}=    Set Variable If    ${expected}==${True}    The flow is expected in ${ds} data store, but    The flow is not expected in ${ds} data store, but
269     ${msgp}=    Set Variable If    ${presence}==${True}    it is present.    it is not present.
270     Return From Keyword    ${msgf} ${msgp}
271
272 Check Config Flow
273     [Arguments]    ${expected}    ${expvalue}
274     [Documentation]    Wrapper keyword that calls "Flow Presence In Config Store" and "Get Presence Failure Message" from this library
275     ...    to verify that the ${expvalue} flow is or is not found in the config store, depending on whether or not it was ${expected}
276     ${presence_flow}    ${msg}=    Flow Presence In Config Store    ${expvalue}
277     ${msgf}=    Get Presence Failure Message    config    ${expected}    ${presence_flow}    ${msg}
278     Should Be Equal    ${expected}    ${presence_flow}    msg=${msgf}
279
280 Check Operational Flow
281     [Arguments]    ${expected}    ${expvalue}
282     [Documentation]    Wrapper keyword that calls "Flow Presence In Operational Store" and "Get Presence Failure Message" from this library
283     ...    to verify that the ${expvalue} flow is or is not found in the config store, depending on whether or not it was ${expected}
284     ${presence_table}    ${msg}=    Flow Presence In Operational Store    ${expvalue}
285     ${msgf}=    Get Presence Failure Message    operational    ${expected}    ${presence_table}    ${msg}
286     Should Be Equal    ${expected}    ${presence_table}    msg=${msgf}
287
288 Add Flow Via RPC
289     [Arguments]    ${node_id}    ${xmlroot}
290     [Documentation]    Deploys a flow specified by given flow details (${node_id}, ${xmlroot}) using add-flow operation.
291     ...    ${xmlroot} is an xml object of parser xml flow details, usually created by Create Flow Variables For Suite From XML File
292     ...    keyword from this library.
293     ${req}=    Copy Element    ${xmlroot}
294     Remove Element    ${req}    id    clear_tail=True
295     Set Element Tag    ${req}    input
296     Set Element Attribute    ${req}    xmlns    urn:opendaylight:flow:service
297     Add Element    ${req}    <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
298     ${nodeelm}=    Get Element    ${req}    node
299     Set Element Attribute    ${nodeelm}    xmlns:inv    urn:opendaylight:inventory
300     Log Element    ${req}
301     ${strxml}=    Element To String    ${req}
302     ${resp}=    RequestsLibrary.Post Request    session    /restconf/operations/sal-flow:add-flow    data=${strxml}
303     Log    ${resp.content}
304     Should Be Equal As Strings    ${resp.status_code}    200
305
306 Add Flow Via Restconf
307     [Arguments]    ${node_id}    ${table_id}    ${flow_body}
308     [Documentation]    Configures a flow specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using POST method
309     Log    ${flow_body}
310     ${resp}=    RequestsLibrary.Post Request    session    ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}    data=${flow_body}
311     Log    ${resp.content}
312     ${msg}=    Set Variable    Adding flow for ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id} failed, http response ${resp.status_code} received.
313     Should Be Equal As Strings    ${resp.status_code}    204    msg=${msg}
314
315 Update Flow Via RPC
316     [Arguments]    ${node_id}    ${configured_flow_body}    ${updating_flow_body}
317     [Documentation]    Updates a flow by using update-flow operation. ${xmlroot} is usually a variable created by
318     ...    Create Flow Variables For Suite From XML File keyword from this library.
319     Log    ${configured_flow_body}
320     Log    ${updating_flow_body}
321     ${xml}    Parse Xml    <input xmlns="urn:opendaylight:flow:service"></input>
322     Log Element    ${xml}
323     ${origflow}=    Parse Xml    ${configured_flow_body}
324     ${updflow}=    Parse Xml    ${updating_flow_body}
325     Remove Element    ${origflow}    id    clear_tail=True
326     Remove Element    ${updflow}    id    clear_tail=True
327     Remove Element Attribute    ${origflow}    xmlns
328     Remove Element Attribute    ${updflow}    xmlns
329     Set Element Tag    ${origflow}    original-flow
330     Set Element Tag    ${updflow}    updated-flow
331     Add Element    ${xml}    ${origflow}
332     Add Element    ${xml}    ${updflow}
333     Add Element    ${xml}    <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
334     ${nodeelm}=    Get Element    ${xml}    node
335     Set Element Attribute    ${nodeelm}    xmlns:inv    urn:opendaylight:inventory
336     Log Element    ${xml}
337     ${strxml}=    Element To String    ${xml}
338     ${resp}=    RequestsLibrary.Post Request    session    /restconf/operations/sal-flow:update-flow    data=${strxml}
339     Log    ${resp.content}
340     Should Be Equal As Strings    ${resp.status_code}    200
341
342 Update Flow Via Restconf
343     [Arguments]    ${node_id}    ${table_id}    ${flow_id}    ${flow_body}
344     [Documentation]    Updates a flow configuration by given flow details (${node_id}, ${table_id}, ${flow_body}) using PUT method
345     Log    ${flow_body}
346     ${resp}=    RequestsLibrary.Put Request    session    ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id}    data=${flow_body}
347     Log    ${resp.content}
348     ${msg}=    Set Variable    Updating flow for ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id} failed, http response ${resp.status_code} received.
349     Should Be Equal As Strings    ${resp.status_code}    200    msg=${msg}
350
351 Delete Flow Via RPC
352     [Arguments]    ${node_id}    ${xmlroot}
353     [Documentation]    Deletes a flow by using remove-flow opearation. ${xmlroot} is usually a variable created by
354     ...    Create Flow Variables For Suite From XML File keyword from this library.
355     ${req}=    Copy Element    ${xmlroot}
356     Remove Element    ${req}    id    clear_tail=True
357     Set Element Tag    ${req}    input
358     Set Element Attribute    ${req}    xmlns    urn:opendaylight:flow:service
359     Add Element    ${req}    <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
360     ${nodeelm}=    Get Element    ${req}    node
361     Set Element Attribute    ${nodeelm}    xmlns:inv    urn:opendaylight:inventory
362     Log Element    ${req}
363     ${strxml}=    Element To String    ${req}
364     ${resp}=    RequestsLibrary.Post Request    session    /restconf/operations/sal-flow:remove-flow    data=${strxml}
365     Log    ${resp.content}
366     Should Be Equal As Strings    ${resp.status_code}    200
367
368 Delete Flow Via Restconf
369     [Arguments]    ${node_id}    ${table_id}    ${flow_id}
370     [Documentation]    Deletes a flow from configuration datastore specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using DELETE method
371     ${resp}=    RequestsLibrary.Delete Request    session    ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id}
372     Log    ${resp.content}
373     ${msg}=    Set Variable    Delete flow for ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id} failed, http response ${resp.status_code} received.
374     Should Be Equal As Strings    ${resp.status_code}    200    msg=${msg}