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