Adjust OF scalability test
[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). TODO: Remove hard dependency on controller HTTP "session".
6 Library           XML
7 Library           String
8 Library           RequestsLibrary
9 Library           ScaleClient.py
10 Library           FlowLib.py
11 Library           XmlComparator.py
12 Library           Common.py
13 Variables         ../variables/Variables.py
14
15 *** Keywords ***
16 Check No Switches In Inventory
17     [Arguments]    ${switches}
18     [Documentation]    Check no switch is in inventory
19     ${resp}    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}
20     Log    ${resp.content}
21     Should Be Equal As Strings    ${resp.status_code}    200
22     : FOR    ${switch}    IN RANGE    1    ${switches+1}
23     \    Should Not Contain    ${resp.content}    "openflow:${switch}"
24
25 Check No Switches In Topology
26     [Arguments]    ${switches}
27     [Documentation]    Check no switch is in topology
28     ${resp}    RequestsLibrary.Get Request    session    ${OPERATIONAL_TOPO_API}
29     Log    ${resp.content}
30     Should Be Equal As Strings    ${resp.status_code}    200
31     : FOR    ${switch}    IN RANGE    1    ${switches+1}
32     \    Should Not Contain    ${resp.content}    openflow:${switch}
33
34 Check Switches In Inventory
35     [Arguments]    ${switches}
36     [Documentation]    Check all switches and stats in operational inventory
37     : FOR    ${switch}    IN RANGE    1    ${switches+1}
38     \    ${resp}    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}/node/openflow:${switch}
39     \    Should Be Equal As Strings    ${resp.status_code}    200
40     \    Should Contain    ${resp.content}    flow-capable-node-connector-statistics
41     \    Should Contain    ${resp.content}    flow-table-statistics
42
43 Check Switches In Topology
44     [Arguments]    ${switches}
45     [Documentation]    Check switches are in the topology.
46     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_TOPO_API}
47     Log    ${resp.content}
48     Should Be Equal As Strings    ${resp.status_code}    200
49     ${count}=    Get Count    ${resp.content}    "node-id":"openflow:
50     BuiltIn.Should Be Equal As Numbers    ${count}    ${switches}
51
52 Check Number Of Links
53     [Arguments]    ${links}
54     [Documentation]    Check number of links in the topolgy.
55     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_TOPO_API}
56     Log    ${resp.content}
57     Should Be Equal As Strings    ${resp.status_code}    200
58     ${count}=    Get Count    ${resp.content}    "link-id":"openflow:
59     Should Be Equal As Integers    ${count}    ${links}
60
61 Check Linear Topology
62     [Arguments]    ${switches}
63     [Documentation]    Check Linear topology.
64     ${resp}    RequestsLibrary.Get Request    session    ${OPERATIONAL_TOPO_API}
65     Log    ${resp.content}
66     Should Be Equal As Strings    ${resp.status_code}    200
67     : FOR    ${switch}    IN RANGE    1    ${switches+1}
68     \    Should Contain    ${resp.content}    "node-id":"openflow:${switch}"
69     \    Should Contain    ${resp.content}    "tp-id":"openflow:${switch}:1"
70     \    Should Contain    ${resp.content}    "tp-id":"openflow:${switch}:2"
71     \    Should Contain    ${resp.content}    "source-tp":"openflow:${switch}:2"
72     \    Should Contain    ${resp.content}    "dest-tp":"openflow:${switch}:2"
73     \    ${edge}    Evaluate    ${switch}==1 or ${switch}==${switches}
74     \    Run Keyword Unless    ${edge}    Should Contain    ${resp.content}    "tp-id":"openflow:${switch}:3"
75     \    Run Keyword Unless    ${edge}    Should Contain    ${resp.content}    "source-tp":"openflow:${switch}:3"
76     \    Run Keyword Unless    ${edge}    Should Contain    ${resp.content}    "dest-tp":"openflow:${switch}:3"
77
78 Check Flows Operational Datastore
79     [Arguments]    ${flow_count}    ${controller_ip}=${ODL_SYSTEM_IP}
80     [Documentation]    Check if number of Operational Flows on member of given index is equal to ${flow_count}.
81     ${sw}    ${reported_flow}    ${found_flow}=    ScaleClient.Flow Stats Collected    controller=${controller_ip}
82     Should_Be_Equal_As_Numbers    ${flow_count}    ${found_flow}
83
84 Check Number Of Flows
85     [Arguments]    ${flows}
86     [Documentation]    Check number of flows in the inventory.
87     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}
88     Log    ${resp.content}
89     Should Be Equal As Strings    ${resp.status_code}    200
90     ${count}=    Get Count    ${resp.content}    "priority"
91     Should Be Equal As Integers    ${count}    ${flows}
92
93 Check Number Of Groups
94     [Arguments]    ${groups}
95     [Documentation]    Check number of groups in the inventory.
96     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}
97     Log    ${resp.content}
98     Should Be Equal As Strings    ${resp.status_code}    200
99     ${group_count}=    Get Count    ${resp.content}    "group-type"
100     ${count}=    CompareStream.Set_Variable_If_At Least_Boron    ${group_count}    ${group_count/2}
101     Should Be Equal As Integers    ${count}    ${groups}
102
103 Check Flow Stats Are Available
104     [Arguments]    ${node_id}    ${flows}
105     [Documentation]    A GET on the /node/${node_id} inventory API is made and flow stats string is checked for existence.
106     ${resp}    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}/node/${node_id}/table/2
107     Log    ${resp.content}
108     Should Be Equal As Strings    ${resp.status_code}    200
109     Should Contain X Times    ${resp.content}    priority    ${flows}
110
111 Check Number Of Hosts
112     [Arguments]    ${hosts}
113     [Documentation]    Check number of hosts in topology
114     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_TOPO_API}
115     Log    ${resp.content}
116     Should Be Equal As Strings    ${resp.status_code}    200
117     ${count}=    Get Count    ${resp.content}    "node-id":"host:
118     Should Be Equal As Integers    ${count}    ${hosts}
119
120 Check No Hosts
121     [Documentation]    Check if all hosts are deleted from inventory
122     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_TOPO_API}
123     Should Be Equal As Strings    ${resp.status_code}    200
124     Should Not Contain    ${resp.content}    "node-id":"host:
125
126 Add Table Miss Flows
127     [Arguments]    ${switches}
128     [Documentation]    Add table miss flows to switches.
129     ${switches}=    Convert To Integer    ${switches}
130     ${data}=    OperatingSystem.Get File    ${CURDIR}/../variables/openflowplugin/table_miss_flow.json
131     : FOR    ${switch}    IN RANGE    1    ${switches+1}
132     \    TemplatedRequests.Put As Json To Uri    ${CONFIG_NODES_API}/node/openflow:${switch}/table/0/flow/default    ${data}    session
133
134 Check Table Miss Flows
135     [Arguments]    ${switches}
136     [Documentation]    Check table miss flows in switches.
137     ${switches}=    Convert To Integer    ${switches}
138     : FOR    ${switch}    IN RANGE    1    ${switches+1}
139     \    TemplatedRequests.Get As Json From Uri    ${OPERATIONAL_NODES_API}/node/openflow:${switch}/table/0/flow/default    session
140
141 Create Inventory Flow
142     [Documentation]    Calls FlowLib.Make_Inventory_Flow function and initializes and sanitizes
143     ...    the basic flow elements that can be given to flow:inventory
144     ${flow}=    Make Inventory Flow
145     [Return]    ${flow}
146
147 Create Service Flow
148     [Documentation]    Used for creating an object that will use an XML format that
149     ...    can be given to flow:service.
150     ${flow}=    Make Service Flow
151     [Return]    ${flow}
152
153 Set "${flow}" "${property}" With "${property_val}"
154     [Documentation]    Embedded variables to make higher level keywords more readable.
155     ...    There are some cases where the python attribute uses an underscore,
156     ...    but a hyphen needs to be used. This seems inconsistent, and may need
157     ...    to be looked at from the openflow plugin perspective.
158     ...
159     ...    At this point, this library will remove the element ${property} from the
160     ...    xml representation of the flow and reset with the given value. \ It's not
161     ...    possible, yet, to have multiple elements with the same name. \ That will
162     ...    likely be needed in the future.
163     ${property}    Run Keyword If    "table_id" != "${property}" and "cookie_mask" != "${property}"    Replace String    ${property}    _    -
164     ...    ELSE    Set Variable    ${property}
165     Remove Flow XML Element    ${flow}    ${property}
166     Add Flow XML Element    ${flow}    ${property}    ${property_val}
167     Set Flow Field    ${flow}    ${property}    ${property_val}
168     [Return]    ${flow}
169
170 Set Flow Action
171     [Arguments]    ${flow}    ${instruction_order}    ${action_order}    ${action}    ${action_val}=${EMPTY}
172     [Documentation]    Will remove the instruction element first, then add the proper xml structure
173     ...    to implement the action as given in the arguments
174     ##For the case that any of the instruction/apply-actions/action elements are not there we need to add them'
175     Remove Flow XML Element    ${flow}    instruction
176     Add Flow XML Element    ${flow}    instruction    ${EMPTY}    instructions
177     Add Flow XML Element    ${flow}    order    ${instruction_order}    instructions/instruction
178     Add Flow XML Element    ${flow}    apply-actions    ${EMPTY}    instructions/instruction
179     Add Flow XML Element    ${flow}    action    ${EMPTY}    instructions/instruction/apply-actions
180     Add Flow XML Element    ${flow}    order    ${action_order}    instructions/instruction/apply-actions/action
181     Add Flow XML Element    ${flow}    ${action}    ${action_val}    instructions/instruction/apply-actions/action
182     [Return]    ${flow}
183
184 Set Flow Output Action
185     [Arguments]    ${flow}    ${instruction_order}    ${action_order}    ${output_port}
186     Set Flow Action    ${flow}    ${instruction_order}    ${action_order}    output-action
187     Add Flow XML Element    ${flow}    output-node-connector    ${output_port}    instructions/instruction/apply-actions/action/output-action
188     [Return]    ${flow}
189
190 Set Flow Ethernet Match
191     [Arguments]    ${flow}    ${match_value_dict}
192     [Documentation]    Specific keyword for adding an ethernet match rules where the elements are given
193     ...    in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any
194     ...    existing ethernet-match elements from the flow before adding
195     Clear Flow Matches    ${flow}    match/ethernet-match
196     Add Flow XML Element    ${flow}    ethernet-match    ${EMPTY}    match
197     ${type}=    Get From Dictionary    ${match_value_dict}    type
198     Add Flow XML Element    ${flow}    ethernet-type    ${EMPTY}    match/ethernet-match
199     Add Flow XML Element    ${flow}    type    ${type}    match/ethernet-match/ethernet-type
200     ${src}=    Get From Dictionary    ${match_value_dict}    source
201     Add Flow XML Element    ${flow}    ethernet-source    ${EMPTY}    match/ethernet-match
202     Add Flow XML Element    ${flow}    address    ${src}    match/ethernet-match/ethernet-source
203     ${dst}=    Get From Dictionary    ${match_value_dict}    destination
204     Add Flow XML Element    ${flow}    ethernet-destination    ${EMPTY}    match/ethernet-match
205     Add Flow XML Element    ${flow}    address    ${dst}    match/ethernet-match/ethernet-destination
206     [Return]    ${flow}
207
208 Set Flow IPv4 Match
209     [Arguments]    ${flow}    ${match_value_dict}
210     [Documentation]    Specific keyword for adding an ipv4 match rules where the elements are given
211     ...    in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any
212     ...    existing ipv4 match elements from the flow before adding
213     Clear Flow Matches    ${flow}    match/ipv4-source
214     Clear Flow Matches    ${flow}    match/ipv4-destination
215     ${src}=    Get From Dictionary    ${match_value_dict}    source
216     Add Flow XML Element    ${flow}    ipv4-source    ${src}    match
217     ${dst}=    Get From Dictionary    ${match_value_dict}    destination
218     Add Flow XML Element    ${flow}    ipv4-destination    ${dst}    match
219     [Return]    ${flow}
220
221 Clear Flow Actions
222     [Arguments]    ${flow}
223     [Documentation]    Will clean out any existing flow actions in the given ${flow} object
224     Remove Flow XML Element    ${flow}    instructions/instruction
225     [Return]    ${flow}
226
227 Clear Flow Matches
228     [Arguments]    ${flow}    ${match_element}
229     [Documentation]    Will clean out any existing flow matches in the given ${flow} object
230     Remove Flow XML Element    ${flow}    match/${match_element}
231     [Return]    ${flow}
232
233 Set Flow XML Element Attribute
234     [Arguments]    ${flow}    ${element}    ${id}    ${value}
235     [Documentation]    Will set the given id/value pair to the given to the element provided
236     ...    and make the proper changes to the ${flow} object also provided.
237     ${flow_xml}=    Parse XML    ${flow.xml}
238     Set Element Attribute    ${flow_xml}    ${id}    ${value}    xpath=${element}
239     ${xml_string}=    Element To String    ${flow_xml}
240     Set Flow Field    ${flow}    xml    ${xml_string}
241     Log    ${flow.xml}
242     [Return]    ${flow}
243
244 Add Flow XML Element
245     [Arguments]    ${flow}    ${element}    ${element_val}=${EMPTY}    ${xpath}=.
246     [Documentation]    Will modify the current xml representation of the ${flow} object to contain
247     ...    the given ${element} at the given ${xpath}. If the ${element} uses a value, that can be
248     ...    passed eith the ${element_val} which defaults to ${EMPTY} if not used. NOTE: since there
249     ...    are two default parameters to this keyword, if you have an ${xpath} to use, but no ${element_val}
250     ...    you will still need to pass ${EMPTY} when invoking so that ${xpath} will end up at the right
251     ...    location in the parameter list
252     ${flow_xml}=    Parse XML    ${flow.xml}
253     Add Element    ${flow_xml}    <${element}>${element_val}</${element}>    xpath=${xpath}
254     ${xml_string}=    Element To String    ${flow_xml}
255     Set Flow Field    ${flow}    xml    ${xml_string}
256     Log    ${flow.xml}
257     [Return]    ${flow}
258
259 Remove Flow XML Element
260     [Arguments]    ${flow}    ${element_xpath}
261     [Documentation]    Removes the element at the given ${element_xpath} within the given ${flow}
262     ...    object. The ${flow} object's xml representation will be updated to reflect this removal.
263     ${flow_xml}=    Parse XML    ${flow.xml}
264     Run Keyword And Ignore Error    Remove Elements    ${flow_xml}    xpath=${element_xpath}
265     ${xml_string}=    Element To String    ${flow_xml}
266     Set Flow Field    ${flow}    xml    ${xml_string}
267     [Return]    ${flow}
268
269 Add Group To Controller And Verify
270     [Arguments]    ${group_body}    ${node_id}    ${group_id}
271     [Documentation]    Push group through REST-API and verify in data-store
272     ${resp}    RequestsLibrary.Put Request    session    ${CONFIG_NODES_API}/node/${node_id}/group/${group_id}    headers=${HEADERS_XML}    data=${group_body}
273     Log    ${resp.content}
274     BuiltIn.Should_Match    "${resp.status_code}"    "20?"
275     ${resp}    RequestsLibrary.Get Request    session    ${CONFIG_NODES_API}/node/${node_id}/group/${group_id}    headers=${ACCEPT_XML}
276     Log    ${resp.content}
277     Should Be Equal As Strings    ${resp.status_code}    200
278     Compare Xml    ${group_body}    ${resp.content}
279
280 Add Flow To Controller And Verify
281     [Arguments]    ${flow_body}    ${node_id}    ${table_id}    ${flow_id}
282     [Documentation]    Push flow through REST-API and verify in data-store
283     ${resp}    RequestsLibrary.Put Request    session    ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id}    headers=${HEADERS_XML}    data=${flow_body}
284     Log    ${resp.content}
285     BuiltIn.Should_Match    "${resp.status_code}"    "20?"
286     ${resp}    RequestsLibrary.Get Request    session    ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id}    headers=${ACCEPT_XML}
287     Log    ${resp.content}
288     Should Be Equal As Strings    ${resp.status_code}    200
289     Compare Xml    ${flow_body}    ${resp.content}
290
291 Verify Flow On Mininet Switch
292     [Arguments]    ${flow_elements}
293     [Documentation]    Checking flow on switch
294     Sleep    1
295     Write    dpctl dump-flows -O OpenFlow13
296     ${switchoutput}    Read Until    >
297     : FOR    ${flowElement}    IN    @{flow_elements}
298     \    Should Contain    ${switchoutput}    ${flowElement}
299
300 Remove Group From Controller And Verify
301     [Arguments]    ${node_id}    ${group_id}
302     [Documentation]    Remove group and verify
303     ${resp}    RequestsLibrary.Delete Request    session    ${CONFIG_NODES_API}/node/${node_id}/group/${group_id}
304     Log    ${resp.content}
305     Should Be Equal As Strings    ${resp.status_code}    200
306     ${resp}    RequestsLibrary.Get Request    session    ${CONFIG_NODES_API}/node/${node_id}/group/${group_id}
307     Builtin.Return_From_Keyword_If    ${resp.status_code} == 404
308     Builtin.Log    ${resp.text}
309     Builtin.Fail    The request failed with code ${resp.status_code}
310
311 Remove Flow From Controller And Verify
312     [Arguments]    ${node_id}    ${table_id}    ${flow_id}
313     [Documentation]    Remove flow and verify
314     ${resp}    RequestsLibrary.Delete Request    session    ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id}
315     Log    ${resp.content}
316     Should Be Equal As Strings    ${resp.status_code}    200
317     ${resp}    RequestsLibrary.Get Request    session    ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id}
318     Builtin.Return_From_Keyword_If    ${resp.status_code} == 404
319     Builtin.Log    ${resp.text}
320     Builtin.Fail    The request failed with code ${resp.status_code}
321
322 Verify Flow Does Not Exist On Mininet Switch
323     [Arguments]    ${flow_elements}
324     [Documentation]    Checking flow on switch is removed
325     Sleep    1
326     Write    dpctl dump-flows -O OpenFlow13
327     ${switchoutput}    Read Until    >
328     : FOR    ${flowElement}    IN    @{flow_elements}
329     \    Should Not Contain    ${switchoutput}    ${flowElement}
330
331 Remove Default Flows
332     [Arguments]    ${node_id}
333     [Documentation]    Removes any flows considered "default". one such flow is
334     ...    to forward all traffic to the CONTROLLER with priority 0 at flow-table 0
335     ...    If/When others are implemented this keyword can be updated to include those.
336     ${flow}=    Make Service Flow
337     Set "${flow}" "priority" With "0"
338     Set "${flow}" "flow-table" With "0"
339     Add Flow XML Element    ${flow}    node    /inv:nodes/inv:node[inv:id="${node_id}"]
340     Set Flow XML Element Attribute    ${flow}    node    xmlns:inv    urn:opendaylight:inventory
341     Log    Flow XML is ${flow.xml}
342     write    dpctl dump-flows -O OpenFlow13
343     ${switchoutput}    Read Until    >
344     ${headers}=    Create Dictionary    Content-Type=application/yang.data+xml
345     ${resp}    RequestsLibrary.Post Request    session    restconf/operations/sal-flow:remove-flow    data=${flow.xml}    headers=${headers}
346     Log    ${resp.content}
347     Should Be Equal As Strings    ${resp.status_code}    200
348     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}
349     Log    ${resp.content}
350     Should Not Contain    ${resp.content}    "output-node-connector": "CONTROLLER",
351     ${strings_to_check_for}=    Create List    CONTROLLER
352     Verify Flow Does Not Exist On Mininet Switch    ${strings_to_check_for}
353
354 Create Flow Variables For Suite From XML File
355     [Arguments]    ${file}
356     [Documentation]    Given the flow XML ${file}, it will create several suite wide variables
357     ${data}=    OperatingSystem.Get File    ${file}
358     ${xmlroot}=    Parse Xml    ${file}
359     ${table_id}=    Get Element Text    ${xmlroot}    table_id
360     ${flow_id}=    Get Element Text    ${xmlroot}    id
361     ${flow_priority}=    Get Element Text    ${xmlroot}    priority
362     ${upddata}=    Get Data For Flow Put Update    ${data}
363     Set Suite Variable    ${table_id}
364     Set Suite Variable    ${flow_id}
365     Set Suite Variable    ${flow_priority}
366     Set Suite Variable    ${data}
367     Set Suite Variable    ${upddata}
368     Set Suite Variable    ${xmlroot}
369
370 Check Datastore Presence
371     [Arguments]    ${fname}    ${reqconfpres}    ${reqoperpres}    ${upd}    ${check_id}=${False}
372     [Documentation]    Checks if flow is properly existing or not existing in the config and operational
373     ...    datastores, based on the variables ${reqconfpres} and ${reqoperpres}
374     Create Flow Variables For Suite From XML File    ${XmlsDir}/${fname}
375     # Note:    ${upddata} and ${data} are suite variables set by the keyword above.
376     ${det}=    Set Variable If    ${upd}==${True}    ${upddata}    ${data}
377     Check Config Flow    ${reqconfpres}    ${det}
378     Check Operational Flow    ${reqoperpres}    ${det}    ${check_id}
379
380 Flow Presence In Config Store
381     [Arguments]    ${expvalue}
382     [Documentation]    Checks the config store for given flow. Returns True if present, otherwise returns False
383     ...    This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx}
384     ${headers}=    Create Dictionary    Accept=application/xml
385     ${resp}=    RequestsLibrary.Get Request    session    ${CONFIG_NODES_API}/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id}    headers=${headers}
386     Log    ${resp}
387     Log    ${resp.content}
388     Return From Keyword If    ${resp.status_code}!=200    ${False}    ${EMPTY}
389     ${pres}    ${msg}=    Is Flow Configured    ${expvalue}    ${resp.content}
390     Run Keyword If    '''${msg}'''!='${EMPTY}'    Log    ${msg}
391     Return From Keyword    ${pres}    ${msg}
392
393 Flow Presence In Operational Store
394     [Arguments]    ${expvalue}    ${check_id}=${False}
395     [Documentation]    Checks the operational store for given flow. Returns True if present, otherwise returns False
396     ...    This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx}
397     ${headers}=    Create Dictionary    Accept=application/xml
398     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}/node/openflow:${switch_idx}/table/${table_id}    headers=${headers}
399     Log    ${resp}
400     Log    ${resp.content}
401     Return From Keyword If    ${resp.status_code}!=200    ${False}    ${EMPTY}
402     ${pres}    ${msg}=    Is Flow Operational2    ${expvalue}    ${resp.content}    ${check_id}
403     Run Keyword If    '''${msg}'''!='${EMPTY}'    Log    ${msg}
404     Return From Keyword    ${pres}    ${msg}
405
406 Get Presence Failure Message
407     [Arguments]    ${ds}    ${expected}    ${presence}    ${diffmsg}
408     [Documentation]    Utility keyword to help manipulate mesage strings that may be used later to PASS or FAIL with
409     Return From Keyword If    '''${diffmsg}'''!='${EMPTY}'    Flow found in ${ds} data store but: ${diffmsg}
410     ${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
411     ${msgp}=    Set Variable If    ${presence}==${True}    it is present.    it is not present.
412     Return From Keyword    ${msgf} ${msgp}
413
414 Check Config Flow
415     [Arguments]    ${expected}    ${expvalue}
416     [Documentation]    Wrapper keyword that calls "Flow Presence In Config Store" and "Get Presence Failure Message" from this library
417     ...    to verify that the ${expvalue} flow is or is not found in the config store, depending on whether or not it was ${expected}
418     ${presence_flow}    ${msg}=    Flow Presence In Config Store    ${expvalue}
419     ${msgf}=    Get Presence Failure Message    config    ${expected}    ${presence_flow}    ${msg}
420     Should Be Equal    ${expected}    ${presence_flow}    msg=${msgf}
421
422 Check Operational Flow
423     [Arguments]    ${expected}    ${expvalue}    ${check_id}=${False}
424     [Documentation]    Wrapper keyword that calls "Flow Presence In Operational Store" and "Get Presence Failure Message" from this library
425     ...    to verify that the ${expvalue} flow is or is not found in the operational store, depending on whether or not it was ${expected}
426     ${presence_table}    ${msg}=    Flow Presence In Operational Store    ${expvalue}    ${check_id}
427     ${msgf}=    Get Presence Failure Message    operational    ${expected}    ${presence_table}    ${msg}
428     Should Be Equal    ${expected}    ${presence_table}    msg=${msgf}
429
430 Add Flow Via RPC
431     [Arguments]    ${node_id}    ${xmlroot}
432     [Documentation]    Deploys a flow specified by given flow details (${node_id}, ${xmlroot}) using add-flow operation.
433     ...    ${xmlroot} is an xml object of parser xml flow details, usually created by Create Flow Variables For Suite From XML File
434     ...    keyword from this library.
435     ${req}=    Copy Element    ${xmlroot}
436     Remove Element    ${req}    id    clear_tail=True
437     Set Element Tag    ${req}    input
438     Set Element Attribute    ${req}    xmlns    urn:opendaylight:flow:service
439     Add Element    ${req}    <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
440     ${nodeelm}=    Get Element    ${req}    node
441     Set Element Attribute    ${nodeelm}    xmlns:inv    urn:opendaylight:inventory
442     Log Element    ${req}
443     ${strxml}=    Element To String    ${req}
444     ${resp}=    RequestsLibrary.Post Request    session    /restconf/operations/sal-flow:add-flow    data=${strxml}
445     Log    ${resp.content}
446     Should Be Equal As Strings    ${resp.status_code}    200
447
448 Add Flow Via Restconf
449     [Arguments]    ${node_id}    ${table_id}    ${flow_body}
450     [Documentation]    Configures a flow specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using POST method
451     Log    ${flow_body}
452     ${resp}=    RequestsLibrary.Post Request    session    ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}    data=${flow_body}
453     Log    ${resp.content}
454     ${msg}=    Set Variable    Adding flow for ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id} failed, http response ${resp.status_code} received.
455     Should Be Equal As Strings    ${resp.status_code}    204    msg=${msg}
456
457 Update Flow Via RPC
458     [Arguments]    ${node_id}    ${configured_flow_body}    ${updating_flow_body}
459     [Documentation]    Updates a flow by using update-flow operation. ${xmlroot} is usually a variable created by
460     ...    Create Flow Variables For Suite From XML File keyword from this library.
461     Log    ${configured_flow_body}
462     Log    ${updating_flow_body}
463     ${xml}    Parse Xml    <input xmlns="urn:opendaylight:flow:service"></input>
464     Log Element    ${xml}
465     ${origflow}=    Parse Xml    ${configured_flow_body}
466     ${updflow}=    Parse Xml    ${updating_flow_body}
467     Remove Element    ${origflow}    id    clear_tail=True
468     Remove Element    ${updflow}    id    clear_tail=True
469     Remove Element Attribute    ${origflow}    xmlns
470     Remove Element Attribute    ${updflow}    xmlns
471     Set Element Tag    ${origflow}    original-flow
472     Set Element Tag    ${updflow}    updated-flow
473     Add Element    ${xml}    ${origflow}
474     Add Element    ${xml}    ${updflow}
475     Add Element    ${xml}    <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
476     ${nodeelm}=    Get Element    ${xml}    node
477     Set Element Attribute    ${nodeelm}    xmlns:inv    urn:opendaylight:inventory
478     Log Element    ${xml}
479     ${strxml}=    Element To String    ${xml}
480     ${resp}=    RequestsLibrary.Post Request    session    /restconf/operations/sal-flow:update-flow    data=${strxml}
481     Log    ${resp.content}
482     Should Be Equal As Strings    ${resp.status_code}    200
483
484 Update Flow Via Restconf
485     [Arguments]    ${node_id}    ${table_id}    ${flow_id}    ${flow_body}
486     [Documentation]    Updates a flow configuration by given flow details (${node_id}, ${table_id}, ${flow_body}) using PUT method
487     Log    ${flow_body}
488     ${resp}=    RequestsLibrary.Put Request    session    ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id}    data=${flow_body}
489     Log    ${resp.content}
490     ${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.
491     Should Be Equal As Strings    ${resp.status_code}    200    msg=${msg}
492
493 Delete Flow Via RPC
494     [Arguments]    ${node_id}    ${xmlroot}
495     [Documentation]    Deletes a flow by using remove-flow opearation. ${xmlroot} is usually a variable created by
496     ...    Create Flow Variables For Suite From XML File keyword from this library.
497     ${req}=    Copy Element    ${xmlroot}
498     Remove Element    ${req}    id    clear_tail=True
499     Set Element Tag    ${req}    input
500     Set Element Attribute    ${req}    xmlns    urn:opendaylight:flow:service
501     Add Element    ${req}    <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
502     ${nodeelm}=    Get Element    ${req}    node
503     Set Element Attribute    ${nodeelm}    xmlns:inv    urn:opendaylight:inventory
504     Log Element    ${req}
505     ${strxml}=    Element To String    ${req}
506     ${resp}=    RequestsLibrary.Post Request    session    /restconf/operations/sal-flow:remove-flow    data=${strxml}
507     Log    ${resp.content}
508     Should Be Equal As Strings    ${resp.status_code}    200
509
510 Delete Flow Via Restconf
511     [Arguments]    ${node_id}    ${table_id}    ${flow_id}
512     [Documentation]    Deletes a flow from configuration datastore specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using DELETE method
513     ${resp}=    RequestsLibrary.Delete Request    session    ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id}
514     Log    ${resp.content}
515     ${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.
516     Should Be Equal As Strings    ${resp.status_code}    200    msg=${msg}