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