Fix l2switch max host 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 Create Inventory Flow
127     [Documentation]    Calls FlowLib.Make_Inventory_Flow function and initializes and sanitizes
128     ...    the basic flow elements that can be given to flow:inventory
129     ${flow}=    Make Inventory Flow
130     [Return]    ${flow}
131
132 Create Service Flow
133     [Documentation]    Used for creating an object that will use an XML format that
134     ...    can be given to flow:service.
135     ${flow}=    Make Service Flow
136     [Return]    ${flow}
137
138 Set "${flow}" "${property}" With "${property_val}"
139     [Documentation]    Embedded variables to make higher level keywords more readable.
140     ...    There are some cases where the python attribute uses an underscore,
141     ...    but a hyphen needs to be used. This seems inconsistent, and may need
142     ...    to be looked at from the openflow plugin perspective.
143     ...
144     ...    At this point, this library will remove the element ${property} from the
145     ...    xml representation of the flow and reset with the given value. \ It's not
146     ...    possible, yet, to have multiple elements with the same name. \ That will
147     ...    likely be needed in the future.
148     ${property}    Run Keyword If    "table_id" != "${property}" and "cookie_mask" != "${property}"    Replace String    ${property}    _    -
149     ...    ELSE    Set Variable    ${property}
150     Remove Flow XML Element    ${flow}    ${property}
151     Add Flow XML Element    ${flow}    ${property}    ${property_val}
152     Set Flow Field    ${flow}    ${property}    ${property_val}
153     [Return]    ${flow}
154
155 Set Flow Action
156     [Arguments]    ${flow}    ${instruction_order}    ${action_order}    ${action}    ${action_val}=${EMPTY}
157     [Documentation]    Will remove the instruction element first, then add the proper xml structure
158     ...    to implement the action as given in the arguments
159     ##For the case that any of the instruction/apply-actions/action elements are not there we need to add them'
160     Remove Flow XML Element    ${flow}    instruction
161     Add Flow XML Element    ${flow}    instruction    ${EMPTY}    instructions
162     Add Flow XML Element    ${flow}    order    ${instruction_order}    instructions/instruction
163     Add Flow XML Element    ${flow}    apply-actions    ${EMPTY}    instructions/instruction
164     Add Flow XML Element    ${flow}    action    ${EMPTY}    instructions/instruction/apply-actions
165     Add Flow XML Element    ${flow}    order    ${action_order}    instructions/instruction/apply-actions/action
166     Add Flow XML Element    ${flow}    ${action}    ${action_val}    instructions/instruction/apply-actions/action
167     [Return]    ${flow}
168
169 Set Flow Output Action
170     [Arguments]    ${flow}    ${instruction_order}    ${action_order}    ${output_port}
171     Set Flow Action    ${flow}    ${instruction_order}    ${action_order}    output-action
172     Add Flow XML Element    ${flow}    output-node-connector    ${output_port}    instructions/instruction/apply-actions/action/output-action
173     [Return]    ${flow}
174
175 Set Flow Ethernet Match
176     [Arguments]    ${flow}    ${match_value_dict}
177     [Documentation]    Specific keyword for adding an ethernet match rules where the elements are given
178     ...    in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any
179     ...    existing ethernet-match elements from the flow before adding
180     Clear Flow Matches    ${flow}    match/ethernet-match
181     Add Flow XML Element    ${flow}    ethernet-match    ${EMPTY}    match
182     ${type}=    Get From Dictionary    ${match_value_dict}    type
183     Add Flow XML Element    ${flow}    ethernet-type    ${EMPTY}    match/ethernet-match
184     Add Flow XML Element    ${flow}    type    ${type}    match/ethernet-match/ethernet-type
185     ${src}=    Get From Dictionary    ${match_value_dict}    source
186     Add Flow XML Element    ${flow}    ethernet-source    ${EMPTY}    match/ethernet-match
187     Add Flow XML Element    ${flow}    address    ${src}    match/ethernet-match/ethernet-source
188     ${dst}=    Get From Dictionary    ${match_value_dict}    destination
189     Add Flow XML Element    ${flow}    ethernet-destination    ${EMPTY}    match/ethernet-match
190     Add Flow XML Element    ${flow}    address    ${dst}    match/ethernet-match/ethernet-destination
191     [Return]    ${flow}
192
193 Set Flow IPv4 Match
194     [Arguments]    ${flow}    ${match_value_dict}
195     [Documentation]    Specific keyword for adding an ipv4 match rules where the elements are given
196     ...    in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any
197     ...    existing ipv4 match elements from the flow before adding
198     Clear Flow Matches    ${flow}    match/ipv4-source
199     Clear Flow Matches    ${flow}    match/ipv4-destination
200     ${src}=    Get From Dictionary    ${match_value_dict}    source
201     Add Flow XML Element    ${flow}    ipv4-source    ${src}    match
202     ${dst}=    Get From Dictionary    ${match_value_dict}    destination
203     Add Flow XML Element    ${flow}    ipv4-destination    ${dst}    match
204     [Return]    ${flow}
205
206 Clear Flow Actions
207     [Arguments]    ${flow}
208     [Documentation]    Will clean out any existing flow actions in the given ${flow} object
209     Remove Flow XML Element    ${flow}    instructions/instruction
210     [Return]    ${flow}
211
212 Clear Flow Matches
213     [Arguments]    ${flow}    ${match_element}
214     [Documentation]    Will clean out any existing flow matches in the given ${flow} object
215     Remove Flow XML Element    ${flow}    match/${match_element}
216     [Return]    ${flow}
217
218 Set Flow XML Element Attribute
219     [Arguments]    ${flow}    ${element}    ${id}    ${value}
220     [Documentation]    Will set the given id/value pair to the given to the element provided
221     ...    and make the proper changes to the ${flow} object also provided.
222     ${flow_xml}=    Parse XML    ${flow.xml}
223     Set Element Attribute    ${flow_xml}    ${id}    ${value}    xpath=${element}
224     ${xml_string}=    Element To String    ${flow_xml}
225     Set Flow Field    ${flow}    xml    ${xml_string}
226     Log    ${flow.xml}
227     [Return]    ${flow}
228
229 Add Flow XML Element
230     [Arguments]    ${flow}    ${element}    ${element_val}=${EMPTY}    ${xpath}=.
231     [Documentation]    Will modify the current xml representation of the ${flow} object to contain
232     ...    the given ${element} at the given ${xpath}. If the ${element} uses a value, that can be
233     ...    passed eith the ${element_val} which defaults to ${EMPTY} if not used. NOTE: since there
234     ...    are two default parameters to this keyword, if you have an ${xpath} to use, but no ${element_val}
235     ...    you will still need to pass ${EMPTY} when invoking so that ${xpath} will end up at the right
236     ...    location in the parameter list
237     ${flow_xml}=    Parse XML    ${flow.xml}
238     Add Element    ${flow_xml}    <${element}>${element_val}</${element}>    xpath=${xpath}
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 Remove Flow XML Element
245     [Arguments]    ${flow}    ${element_xpath}
246     [Documentation]    Removes the element at the given ${element_xpath} within the given ${flow}
247     ...    object. The ${flow} object's xml representation will be updated to reflect this removal.
248     ${flow_xml}=    Parse XML    ${flow.xml}
249     Run Keyword And Ignore Error    Remove Elements    ${flow_xml}    xpath=${element_xpath}
250     ${xml_string}=    Element To String    ${flow_xml}
251     Set Flow Field    ${flow}    xml    ${xml_string}
252     [Return]    ${flow}
253
254 Add Group To Controller And Verify
255     [Arguments]    ${group_body}    ${node_id}    ${group_id}
256     [Documentation]    Push group through REST-API and verify in data-store
257     ${resp}    RequestsLibrary.Put Request    session    ${CONFIG_NODES_API}/node/${node_id}/group/${group_id}    headers=${HEADERS_XML}    data=${group_body}
258     Log    ${resp.content}
259     BuiltIn.Should_Match    "${resp.status_code}"    "20?"
260     ${resp}    RequestsLibrary.Get Request    session    ${CONFIG_NODES_API}/node/${node_id}/group/${group_id}    headers=${ACCEPT_XML}
261     Log    ${resp.content}
262     Should Be Equal As Strings    ${resp.status_code}    200
263     Compare Xml    ${group_body}    ${resp.content}
264
265 Add Flow To Controller And Verify
266     [Arguments]    ${flow_body}    ${node_id}    ${table_id}    ${flow_id}
267     [Documentation]    Push flow through REST-API and verify in data-store
268     ${resp}    RequestsLibrary.Put Request    session    ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id}    headers=${HEADERS_XML}    data=${flow_body}
269     Log    ${resp.content}
270     BuiltIn.Should_Match    "${resp.status_code}"    "20?"
271     ${resp}    RequestsLibrary.Get Request    session    ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id}    headers=${ACCEPT_XML}
272     Log    ${resp.content}
273     Should Be Equal As Strings    ${resp.status_code}    200
274     Compare Xml    ${flow_body}    ${resp.content}
275
276 Verify Flow On Mininet Switch
277     [Arguments]    ${flow_elements}
278     [Documentation]    Checking flow on switch
279     Sleep    1
280     Write    dpctl dump-flows -O OpenFlow13
281     ${switchoutput}    Read Until    >
282     : FOR    ${flowElement}    IN    @{flow_elements}
283     \    Should Contain    ${switchoutput}    ${flowElement}
284
285 Remove Group From Controller And Verify
286     [Arguments]    ${node_id}    ${group_id}
287     [Documentation]    Remove group and verify
288     ${resp}    RequestsLibrary.Delete Request    session    ${CONFIG_NODES_API}/node/${node_id}/group/${group_id}
289     Log    ${resp.content}
290     Should Be Equal As Strings    ${resp.status_code}    200
291     ${resp}    RequestsLibrary.Get Request    session    ${CONFIG_NODES_API}/node/${node_id}/group/${group_id}
292     Builtin.Return_From_Keyword_If    ${resp.status_code} == 404
293     Builtin.Log    ${resp.text}
294     Builtin.Fail    The request failed with code ${resp.status_code}
295
296 Remove Flow From Controller And Verify
297     [Arguments]    ${node_id}    ${table_id}    ${flow_id}
298     [Documentation]    Remove flow and verify
299     ${resp}    RequestsLibrary.Delete Request    session    ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id}
300     Log    ${resp.content}
301     Should Be Equal As Strings    ${resp.status_code}    200
302     ${resp}    RequestsLibrary.Get Request    session    ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id}
303     Builtin.Return_From_Keyword_If    ${resp.status_code} == 404
304     Builtin.Log    ${resp.text}
305     Builtin.Fail    The request failed with code ${resp.status_code}
306
307 Verify Flow Does Not Exist On Mininet Switch
308     [Arguments]    ${flow_elements}
309     [Documentation]    Checking flow on switch is removed
310     Sleep    1
311     Write    dpctl dump-flows -O OpenFlow13
312     ${switchoutput}    Read Until    >
313     : FOR    ${flowElement}    IN    @{flow_elements}
314     \    Should Not Contain    ${switchoutput}    ${flowElement}
315
316 Remove Default Flows
317     [Arguments]    ${node_id}
318     [Documentation]    Removes any flows considered "default". one such flow is
319     ...    to forward all traffic to the CONTROLLER with priority 0 at flow-table 0
320     ...    If/When others are implemented this keyword can be updated to include those.
321     ${flow}=    Make Service Flow
322     Set "${flow}" "priority" With "0"
323     Set "${flow}" "flow-table" With "0"
324     Add Flow XML Element    ${flow}    node    /inv:nodes/inv:node[inv:id="${node_id}"]
325     Set Flow XML Element Attribute    ${flow}    node    xmlns:inv    urn:opendaylight:inventory
326     Log    Flow XML is ${flow.xml}
327     write    dpctl dump-flows -O OpenFlow13
328     ${switchoutput}    Read Until    >
329     ${headers}=    Create Dictionary    Content-Type=application/yang.data+xml
330     ${resp}    RequestsLibrary.Post Request    session    restconf/operations/sal-flow:remove-flow    data=${flow.xml}    headers=${headers}
331     Log    ${resp.content}
332     Should Be Equal As Strings    ${resp.status_code}    200
333     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}
334     Log    ${resp.content}
335     Should Not Contain    ${resp.content}    "output-node-connector": "CONTROLLER",
336     ${strings_to_check_for}=    Create List    CONTROLLER
337     Verify Flow Does Not Exist On Mininet Switch    ${strings_to_check_for}
338
339 Create Flow Variables For Suite From XML File
340     [Arguments]    ${file}
341     [Documentation]    Given the flow XML ${file}, it will create several suite wide variables
342     ${data}=    OperatingSystem.Get File    ${file}
343     ${xmlroot}=    Parse Xml    ${file}
344     ${table_id}=    Get Element Text    ${xmlroot}    table_id
345     ${flow_id}=    Get Element Text    ${xmlroot}    id
346     ${flow_priority}=    Get Element Text    ${xmlroot}    priority
347     ${upddata}=    Get Data For Flow Put Update    ${data}
348     Set Suite Variable    ${table_id}
349     Set Suite Variable    ${flow_id}
350     Set Suite Variable    ${flow_priority}
351     Set Suite Variable    ${data}
352     Set Suite Variable    ${upddata}
353     Set Suite Variable    ${xmlroot}
354
355 Check Datastore Presence
356     [Arguments]    ${fname}    ${reqconfpres}    ${reqoperpres}    ${upd}    ${check_id}=${False}
357     [Documentation]    Checks if flow is properly existing or not existing in the config and operational
358     ...    datastores, based on the variables ${reqconfpres} and ${reqoperpres}
359     Create Flow Variables For Suite From XML File    ${XmlsDir}/${fname}
360     # Note:    ${upddata} and ${data} are suite variables set by the keyword above.
361     ${det}=    Set Variable If    ${upd}==${True}    ${upddata}    ${data}
362     Check Config Flow    ${reqconfpres}    ${det}
363     Check Operational Flow    ${reqoperpres}    ${det}    ${check_id}
364
365 Flow Presence In Config Store
366     [Arguments]    ${expvalue}
367     [Documentation]    Checks the config store for given flow. Returns True if present, otherwise returns False
368     ...    This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx}
369     ${headers}=    Create Dictionary    Accept=application/xml
370     ${resp}=    RequestsLibrary.Get Request    session    ${CONFIG_NODES_API}/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id}    headers=${headers}
371     Log    ${resp}
372     Log    ${resp.content}
373     Return From Keyword If    ${resp.status_code}!=200    ${False}    ${EMPTY}
374     ${pres}    ${msg}=    Is Flow Configured    ${expvalue}    ${resp.content}
375     Run Keyword If    '''${msg}'''!='${EMPTY}'    Log    ${msg}
376     Return From Keyword    ${pres}    ${msg}
377
378 Flow Presence In Operational Store
379     [Arguments]    ${expvalue}    ${check_id}=${False}
380     [Documentation]    Checks the operational store for given flow. Returns True if present, otherwise returns False
381     ...    This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx}
382     ${headers}=    Create Dictionary    Accept=application/xml
383     ${resp}=    RequestsLibrary.Get Request    session    ${OPERATIONAL_NODES_API}/node/openflow:${switch_idx}/table/${table_id}    headers=${headers}
384     Log    ${resp}
385     Log    ${resp.content}
386     Return From Keyword If    ${resp.status_code}!=200    ${False}    ${EMPTY}
387     ${pres}    ${msg}=    Is Flow Operational2    ${expvalue}    ${resp.content}    ${check_id}
388     Run Keyword If    '''${msg}'''!='${EMPTY}'    Log    ${msg}
389     Return From Keyword    ${pres}    ${msg}
390
391 Get Presence Failure Message
392     [Arguments]    ${ds}    ${expected}    ${presence}    ${diffmsg}
393     [Documentation]    Utility keyword to help manipulate mesage strings that may be used later to PASS or FAIL with
394     Return From Keyword If    '''${diffmsg}'''!='${EMPTY}'    Flow found in ${ds} data store but: ${diffmsg}
395     ${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
396     ${msgp}=    Set Variable If    ${presence}==${True}    it is present.    it is not present.
397     Return From Keyword    ${msgf} ${msgp}
398
399 Check Config Flow
400     [Arguments]    ${expected}    ${expvalue}
401     [Documentation]    Wrapper keyword that calls "Flow Presence In Config Store" and "Get Presence Failure Message" from this library
402     ...    to verify that the ${expvalue} flow is or is not found in the config store, depending on whether or not it was ${expected}
403     ${presence_flow}    ${msg}=    Flow Presence In Config Store    ${expvalue}
404     ${msgf}=    Get Presence Failure Message    config    ${expected}    ${presence_flow}    ${msg}
405     Should Be Equal    ${expected}    ${presence_flow}    msg=${msgf}
406
407 Check Operational Flow
408     [Arguments]    ${expected}    ${expvalue}    ${check_id}=${False}
409     [Documentation]    Wrapper keyword that calls "Flow Presence In Operational Store" and "Get Presence Failure Message" from this library
410     ...    to verify that the ${expvalue} flow is or is not found in the operational store, depending on whether or not it was ${expected}
411     ${presence_table}    ${msg}=    Flow Presence In Operational Store    ${expvalue}    ${check_id}
412     ${msgf}=    Get Presence Failure Message    operational    ${expected}    ${presence_table}    ${msg}
413     Should Be Equal    ${expected}    ${presence_table}    msg=${msgf}
414
415 Add Flow Via RPC
416     [Arguments]    ${node_id}    ${xmlroot}
417     [Documentation]    Deploys a flow specified by given flow details (${node_id}, ${xmlroot}) using add-flow operation.
418     ...    ${xmlroot} is an xml object of parser xml flow details, usually created by Create Flow Variables For Suite From XML File
419     ...    keyword from this library.
420     ${req}=    Copy Element    ${xmlroot}
421     Remove Element    ${req}    id    clear_tail=True
422     Set Element Tag    ${req}    input
423     Set Element Attribute    ${req}    xmlns    urn:opendaylight:flow:service
424     Add Element    ${req}    <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
425     ${nodeelm}=    Get Element    ${req}    node
426     Set Element Attribute    ${nodeelm}    xmlns:inv    urn:opendaylight:inventory
427     Log Element    ${req}
428     ${strxml}=    Element To String    ${req}
429     ${resp}=    RequestsLibrary.Post Request    session    /restconf/operations/sal-flow:add-flow    data=${strxml}
430     Log    ${resp.content}
431     Should Be Equal As Strings    ${resp.status_code}    200
432
433 Add Flow Via Restconf
434     [Arguments]    ${node_id}    ${table_id}    ${flow_body}
435     [Documentation]    Configures a flow specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using POST method
436     Log    ${flow_body}
437     ${resp}=    RequestsLibrary.Post Request    session    ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}    data=${flow_body}
438     Log    ${resp.content}
439     ${msg}=    Set Variable    Adding flow for ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id} failed, http response ${resp.status_code} received.
440     Should Be Equal As Strings    ${resp.status_code}    204    msg=${msg}
441
442 Update Flow Via RPC
443     [Arguments]    ${node_id}    ${configured_flow_body}    ${updating_flow_body}
444     [Documentation]    Updates a flow by using update-flow operation. ${xmlroot} is usually a variable created by
445     ...    Create Flow Variables For Suite From XML File keyword from this library.
446     Log    ${configured_flow_body}
447     Log    ${updating_flow_body}
448     ${xml}    Parse Xml    <input xmlns="urn:opendaylight:flow:service"></input>
449     Log Element    ${xml}
450     ${origflow}=    Parse Xml    ${configured_flow_body}
451     ${updflow}=    Parse Xml    ${updating_flow_body}
452     Remove Element    ${origflow}    id    clear_tail=True
453     Remove Element    ${updflow}    id    clear_tail=True
454     Remove Element Attribute    ${origflow}    xmlns
455     Remove Element Attribute    ${updflow}    xmlns
456     Set Element Tag    ${origflow}    original-flow
457     Set Element Tag    ${updflow}    updated-flow
458     Add Element    ${xml}    ${origflow}
459     Add Element    ${xml}    ${updflow}
460     Add Element    ${xml}    <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
461     ${nodeelm}=    Get Element    ${xml}    node
462     Set Element Attribute    ${nodeelm}    xmlns:inv    urn:opendaylight:inventory
463     Log Element    ${xml}
464     ${strxml}=    Element To String    ${xml}
465     ${resp}=    RequestsLibrary.Post Request    session    /restconf/operations/sal-flow:update-flow    data=${strxml}
466     Log    ${resp.content}
467     Should Be Equal As Strings    ${resp.status_code}    200
468
469 Update Flow Via Restconf
470     [Arguments]    ${node_id}    ${table_id}    ${flow_id}    ${flow_body}
471     [Documentation]    Updates a flow configuration by given flow details (${node_id}, ${table_id}, ${flow_body}) using PUT method
472     Log    ${flow_body}
473     ${resp}=    RequestsLibrary.Put Request    session    ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id}    data=${flow_body}
474     Log    ${resp.content}
475     ${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.
476     Should Be Equal As Strings    ${resp.status_code}    200    msg=${msg}
477
478 Delete Flow Via RPC
479     [Arguments]    ${node_id}    ${xmlroot}
480     [Documentation]    Deletes a flow by using remove-flow opearation. ${xmlroot} is usually a variable created by
481     ...    Create Flow Variables For Suite From XML File keyword from this library.
482     ${req}=    Copy Element    ${xmlroot}
483     Remove Element    ${req}    id    clear_tail=True
484     Set Element Tag    ${req}    input
485     Set Element Attribute    ${req}    xmlns    urn:opendaylight:flow:service
486     Add Element    ${req}    <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
487     ${nodeelm}=    Get Element    ${req}    node
488     Set Element Attribute    ${nodeelm}    xmlns:inv    urn:opendaylight:inventory
489     Log Element    ${req}
490     ${strxml}=    Element To String    ${req}
491     ${resp}=    RequestsLibrary.Post Request    session    /restconf/operations/sal-flow:remove-flow    data=${strxml}
492     Log    ${resp.content}
493     Should Be Equal As Strings    ${resp.status_code}    200
494
495 Delete Flow Via Restconf
496     [Arguments]    ${node_id}    ${table_id}    ${flow_id}
497     [Documentation]    Deletes a flow from configuration datastore specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using DELETE method
498     ${resp}=    RequestsLibrary.Delete Request    session    ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id}
499     Log    ${resp.content}
500     ${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.
501     Should Be Equal As Strings    ${resp.status_code}    200    msg=${msg}