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