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