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
7 Library RequestsLibrary
9 Library ./XmlComparator.py
11 Variables ../variables/Variables.py
16 Check Flow Stats Are Available
17 [Arguments] ${node_id} ${flows}
18 [Documentation] A GET on the /node/${node_id} inventory API is made and flow stats string is checked for existence.
19 ${resp} RequestsLibrary.Get Request session ${OPERATIONAL_NODES_API}/node/${node_id}/table/2
21 Should Be Equal As Strings ${resp.status_code} 200
22 Should Contain X Times ${resp.content} priority ${flows}
25 [Documentation] Calls FlowLib.Make_Inventory_Flow function and initializes and sanitizes
26 ... the basic flow elements that can be given to flow:inventory
27 ${flow}= Make Inventory Flow
31 [Documentation] Used for creating an object that will use an XML format that
32 ... can be given to flow:service.
33 ${flow}= Make Service Flow
36 Set "${flow}" "${property}" With "${property_val}"
37 [Documentation] Embedded variables to make higher level keywords more readable.
38 ... There are some cases where the python attribute uses an underscore,
39 ... but a hyphen needs to be used. This seems inconsistent, and may need
40 ... to be looked at from the openflow plugin perspective.
42 ... At this point, this library will remove the element ${property} from the
43 ... xml representation of the flow and reset with the given value. \ It's not
44 ... possible, yet, to have multiple elements with the same name. \ That will
45 ... likely be needed in the future.
46 ${property} Run Keyword If "table_id" != "${property}" and "cookie_mask" != "${property}" Replace String ${property} _ -
47 ... ELSE Set Variable ${property}
48 Remove Flow XML Element ${flow} ${property}
49 Add Flow XML Element ${flow} ${property} ${property_val}
50 Set Flow Field ${flow} ${property} ${property_val}
54 [Arguments] ${flow} ${instruction_order} ${action_order} ${action} ${action_val}=${EMPTY}
55 [Documentation] Will remove the instruction element first, then add the proper xml structure
56 ... to implement the action as given in the arguments
57 ##For the case that any of the instruction/apply-actions/action elements are not there we need to add them'
58 Remove Flow XML Element ${flow} instruction
59 Add Flow XML Element ${flow} instruction ${EMPTY} instructions
60 Add Flow XML Element ${flow} order ${instruction_order} instructions/instruction
61 Add Flow XML Element ${flow} apply-actions ${EMPTY} instructions/instruction
62 Add Flow XML Element ${flow} action ${EMPTY} instructions/instruction/apply-actions
63 Add Flow XML Element ${flow} order ${action_order} instructions/instruction/apply-actions/action
64 Add Flow XML Element ${flow} ${action} ${action_val} instructions/instruction/apply-actions/action
67 Set Flow Output Action
68 [Arguments] ${flow} ${instruction_order} ${action_order} ${output_port}
69 Set Flow Action ${flow} ${instruction_order} ${action_order} output-action
70 Add Flow XML Element ${flow} output-node-connector ${output_port} instructions/instruction/apply-actions/action/output-action
73 Set Flow Ethernet Match
74 [Arguments] ${flow} ${match_value_dict}
75 [Documentation] Specific keyword for adding an ethernet match rules where the elements are given
76 ... in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any
77 ... existing ethernet-match elements from the flow before adding
78 Clear Flow Matches ${flow} match/ethernet-match
79 Add Flow XML Element ${flow} ethernet-match ${EMPTY} match
80 ${type}= Get From Dictionary ${match_value_dict} type
81 Add Flow XML Element ${flow} ethernet-type ${EMPTY} match/ethernet-match
82 Add Flow XML Element ${flow} type ${type} match/ethernet-match/ethernet-type
83 ${src}= Get From Dictionary ${match_value_dict} source
84 Add Flow XML Element ${flow} ethernet-source ${EMPTY} match/ethernet-match
85 Add Flow XML Element ${flow} address ${src} match/ethernet-match/ethernet-source
86 ${dst}= Get From Dictionary ${match_value_dict} destination
87 Add Flow XML Element ${flow} ethernet-destination ${EMPTY} match/ethernet-match
88 Add Flow XML Element ${flow} address ${dst} match/ethernet-match/ethernet-destination
92 [Arguments] ${flow} ${match_value_dict}
93 [Documentation] Specific keyword for adding an ipv4 match rules where the elements are given
94 ... in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any
95 ... existing ipv4 match elements from the flow before adding
96 Clear Flow Matches ${flow} match/ipv4-source
97 Clear Flow Matches ${flow} match/ipv4-destination
98 ${src}= Get From Dictionary ${match_value_dict} source
99 Add Flow XML Element ${flow} ipv4-source ${src} match
100 ${dst}= Get From Dictionary ${match_value_dict} destination
101 Add Flow XML Element ${flow} ipv4-destination ${dst} match
106 [Documentation] Will clean out any existing flow actions in the given ${flow} object
107 Remove Flow XML Element ${flow} instructions/instruction
111 [Arguments] ${flow} ${match_element}
112 [Documentation] Will clean out any existing flow matches in the given ${flow} object
113 Remove Flow XML Element ${flow} match/${match_element}
116 Set Flow XML Element Attribute
117 [Arguments] ${flow} ${element} ${id} ${value}
118 [Documentation] Will set the given id/value pair to the given to the element provided
119 ... and make the proper changes to the ${flow} object also provided.
120 ${flow_xml}= Parse XML ${flow.xml}
121 Set Element Attribute ${flow_xml} ${id} ${value} xpath=${element}
122 ${xml_string}= Element To String ${flow_xml}
123 Set Flow Field ${flow} xml ${xml_string}
128 [Arguments] ${flow} ${element} ${element_val}=${EMPTY} ${xpath}=.
129 [Documentation] Will modify the current xml representation of the ${flow} object to contain
130 ... the given ${element} at the given ${xpath}. If the ${element} uses a value, that can be
131 ... passed eith the ${element_val} which defaults to ${EMPTY} if not used. NOTE: since there
132 ... are two default parameters to this keyword, if you have an ${xpath} to use, but no ${element_val}
133 ... you will still need to pass ${EMPTY} when invoking so that ${xpath} will end up at the right
134 ... location in the parameter list
135 ${flow_xml}= Parse XML ${flow.xml}
136 Add Element ${flow_xml} <${element}>${element_val}</${element}> xpath=${xpath}
137 ${xml_string}= Element To String ${flow_xml}
138 Set Flow Field ${flow} xml ${xml_string}
142 Remove Flow XML Element
143 [Arguments] ${flow} ${element_xpath}
144 [Documentation] Removes the element at the given ${element_xpath} within the given ${flow}
145 ... object. The ${flow} object's xml representation will be updated to reflect this removal.
146 ${flow_xml}= Parse XML ${flow.xml}
147 Run Keyword And Ignore Error Remove Elements ${flow_xml} xpath=${element_xpath}
148 ${xml_string}= Element To String ${flow_xml}
149 Set Flow Field ${flow} xml ${xml_string}
152 Add Group To Controller And Verify
153 [Arguments] ${group_body} ${node_id} ${group_id}
154 [Documentation] Push group through REST-API and verify in data-store
155 ${resp} RequestsLibrary.Put Request session ${CONFIG_NODES_API}/node/${node_id}/group/${group_id} headers=${HEADERS_XML} data=${group_body}
157 BuiltIn.Should_Match "${resp.status_code}" "20?"
158 ${resp} RequestsLibrary.Get Request session ${CONFIG_NODES_API}/node/${node_id}/group/${group_id} headers=${ACCEPT_XML}
160 Should Be Equal As Strings ${resp.status_code} 200
161 Compare Xml ${group_body} ${resp.content}
163 Add Flow To Controller And Verify
164 [Arguments] ${flow_body} ${node_id} ${table_id} ${flow_id}
165 [Documentation] Push flow through REST-API and verify in data-store
166 ${resp} RequestsLibrary.Put Request session ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id} headers=${HEADERS_XML} data=${flow_body}
168 BuiltIn.Should_Match "${resp.status_code}" "20?"
169 ${resp} RequestsLibrary.Get Request session ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id} headers=${ACCEPT_XML}
171 Should Be Equal As Strings ${resp.status_code} 200
172 Compare Xml ${flow_body} ${resp.content}
174 Verify Flow On Mininet Switch
175 [Arguments] ${flow_elements}
176 [Documentation] Checking flow on switch
178 Write dpctl dump-flows -O OpenFlow13
179 ${switchoutput} Read Until >
180 : FOR ${flowElement} IN @{flow_elements}
181 \ Should Contain ${switchoutput} ${flowElement}
183 Remove Group From Controller And Verify
184 [Arguments] ${node_id} ${group_id}
185 [Documentation] Remove group and verify
186 ${resp} RequestsLibrary.Delete Request session ${CONFIG_NODES_API}/node/${node_id}/group/${group_id}
188 Should Be Equal As Strings ${resp.status_code} 200
189 ${resp} RequestsLibrary.Get Request session ${CONFIG_NODES_API}/node/${node_id}/group/${group_id}
190 Builtin.Return_From_Keyword_If ${resp.status_code} == 404
191 Builtin.Log ${resp.text}
192 Builtin.Fail The request failed with code ${resp.status_code}
194 Remove Flow From Controller And Verify
195 [Arguments] ${node_id} ${table_id} ${flow_id}
196 [Documentation] Remove flow and verify
197 ${resp} RequestsLibrary.Delete Request session ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id}
199 Should Be Equal As Strings ${resp.status_code} 200
200 ${resp} RequestsLibrary.Get Request session ${CONFIG_NODES_API}/node/${node_id}/table/${table_id}/flow/${flow_id}
201 Builtin.Return_From_Keyword_If ${resp.status_code} == 404
202 Builtin.Log ${resp.text}
203 Builtin.Fail The request failed with code ${resp.status_code}
205 Verify Flow Does Not Exist On Mininet Switch
206 [Arguments] ${flow_elements}
207 [Documentation] Checking flow on switch is removed
209 Write dpctl dump-flows -O OpenFlow13
210 ${switchoutput} Read Until >
211 : FOR ${flowElement} IN @{flow_elements}
212 \ Should Not Contain ${switchoutput} ${flowElement}
215 [Arguments] ${node_id}
216 [Documentation] Removes any flows considered "default". one such flow is
217 ... to forward all traffic to the CONTROLLER with priority 0 at flow-table 0
218 ... If/When others are implemented this keyword can be updated to include those.
219 ${flow}= Make Service Flow
220 Set "${flow}" "priority" With "0"
221 Set "${flow}" "flow-table" With "0"
222 Add Flow XML Element ${flow} node /inv:nodes/inv:node[inv:id="${node_id}"]
223 Set Flow XML Element Attribute ${flow} node xmlns:inv urn:opendaylight:inventory
224 Log Flow XML is ${flow.xml}
225 write dpctl dump-flows -O OpenFlow13
226 ${switchoutput} Read Until >
227 ${headers}= Create Dictionary Content-Type=application/yang.data+xml
228 ${resp} RequestsLibrary.Post Request session restconf/operations/sal-flow:remove-flow data=${flow.xml} headers=${headers}
230 Should Be Equal As Strings ${resp.status_code} 200
231 ${resp}= RequestsLibrary.Get Request session ${OPERATIONAL_NODES_API}
233 Should Not Contain ${resp.content} "output-node-connector": "CONTROLLER",
234 ${strings_to_check_for}= Create List CONTROLLER
235 Verify Flow Does Not Exist On Mininet Switch ${strings_to_check_for}
237 Create Flow Variables For Suite From XML File
239 [Documentation] Given the flow XML ${file}, it will create several suite wide variables
240 ${data}= OperatingSystem.Get File ${file}
241 ${xmlroot}= Parse Xml ${file}
242 ${table_id}= Get Element Text ${xmlroot} table_id
243 ${flow_id}= Get Element Text ${xmlroot} id
244 ${flow_priority}= Get Element Text ${xmlroot} priority
245 ${upddata}= Get Data For Flow Put Update ${data}
246 Set Suite Variable ${table_id}
247 Set Suite Variable ${flow_id}
248 Set Suite Variable ${flow_priority}
249 Set Suite Variable ${data}
250 Set Suite Variable ${upddata}
251 Set Suite Variable ${xmlroot}
253 Check Datastore Presence
254 [Arguments] ${fname} ${reqconfpres} ${reqoperpres} ${upd} ${check_id}=${False}
255 [Documentation] Checks if flow is properly existing or not existing in the config and operational
256 ... datastores, based on the variables ${reqconfpres} and ${reqoperpres}
257 Create Flow Variables For Suite From XML File ${XmlsDir}/${fname}
258 # Note: ${upddata} and ${data} are suite variables set by the keyword above.
259 ${det}= Set Variable If ${upd}==${True} ${upddata} ${data}
260 Check Config Flow ${reqconfpres} ${det}
261 Check Operational Flow ${reqoperpres} ${det} ${check_id}
263 Flow Presence In Config Store
264 [Arguments] ${expvalue}
265 [Documentation] Checks the config store for given flow. Returns True if present, otherwise returns False
266 ... This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx}
267 ${headers}= Create Dictionary Accept=application/xml
268 ${resp}= RequestsLibrary.Get Request session ${CONFIG_NODES_API}/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id} headers=${headers}
271 Return From Keyword If ${resp.status_code}!=200 ${False} ${EMPTY}
272 ${pres} ${msg}= Is Flow Configured ${expvalue} ${resp.content}
273 Run Keyword If '''${msg}'''!='${EMPTY}' Log ${msg}
274 Return From Keyword ${pres} ${msg}
276 Flow Presence In Operational Store
277 [Arguments] ${expvalue} ${check_id}=${False}
278 [Documentation] Checks the operational store for given flow. Returns True if present, otherwise returns False
279 ... This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx}
280 ${headers}= Create Dictionary Accept=application/xml
281 ${resp}= RequestsLibrary.Get Request session ${OPERATIONAL_NODES_API}/node/openflow:${switch_idx}/table/${table_id} headers=${headers}
284 Return From Keyword If ${resp.status_code}!=200 ${False} ${EMPTY}
285 ${pres} ${msg}= Is Flow Operational2 ${expvalue} ${resp.content} ${check_id}
286 Run Keyword If '''${msg}'''!='${EMPTY}' Log ${msg}
287 Return From Keyword ${pres} ${msg}
289 Get Presence Failure Message
290 [Arguments] ${ds} ${expected} ${presence} ${diffmsg}
291 [Documentation] Utility keyword to help manipulate mesage strings that may be used later to PASS or FAIL with
292 Return From Keyword If '''${diffmsg}'''!='${EMPTY}' Flow found in ${ds} data store but: ${diffmsg}
293 ${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
294 ${msgp}= Set Variable If ${presence}==${True} it is present. it is not present.
295 Return From Keyword ${msgf} ${msgp}
298 [Arguments] ${expected} ${expvalue}
299 [Documentation] Wrapper keyword that calls "Flow Presence In Config Store" and "Get Presence Failure Message" from this library
300 ... to verify that the ${expvalue} flow is or is not found in the config store, depending on whether or not it was ${expected}
301 ${presence_flow} ${msg}= Flow Presence In Config Store ${expvalue}
302 ${msgf}= Get Presence Failure Message config ${expected} ${presence_flow} ${msg}
303 Should Be Equal ${expected} ${presence_flow} msg=${msgf}
305 Check Operational Flow
306 [Arguments] ${expected} ${expvalue} ${check_id}=${False}
307 [Documentation] Wrapper keyword that calls "Flow Presence In Operational Store" and "Get Presence Failure Message" from this library
308 ... to verify that the ${expvalue} flow is or is not found in the operational store, depending on whether or not it was ${expected}
309 ${presence_table} ${msg}= Flow Presence In Operational Store ${expvalue} ${check_id}
310 ${msgf}= Get Presence Failure Message operational ${expected} ${presence_table} ${msg}
311 Should Be Equal ${expected} ${presence_table} msg=${msgf}
314 [Arguments] ${node_id} ${xmlroot}
315 [Documentation] Deploys a flow specified by given flow details (${node_id}, ${xmlroot}) using add-flow operation.
316 ... ${xmlroot} is an xml object of parser xml flow details, usually created by Create Flow Variables For Suite From XML File
317 ... keyword from this library.
318 ${req}= Copy Element ${xmlroot}
319 Remove Element ${req} id clear_tail=True
320 Set Element Tag ${req} input
321 Set Element Attribute ${req} xmlns urn:opendaylight:flow:service
322 Add Element ${req} <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
323 ${nodeelm}= Get Element ${req} node
324 Set Element Attribute ${nodeelm} xmlns:inv urn:opendaylight:inventory
326 ${strxml}= Element To String ${req}
327 ${resp}= RequestsLibrary.Post Request session /restconf/operations/sal-flow:add-flow data=${strxml}
329 Should Be Equal As Strings ${resp.status_code} 200
331 Add Flow Via Restconf
332 [Arguments] ${node_id} ${table_id} ${flow_body}
333 [Documentation] Configures a flow specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using POST method
335 ${resp}= RequestsLibrary.Post Request session ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id} data=${flow_body}
337 ${msg}= Set Variable Adding flow for ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id} failed, http response ${resp.status_code} received.
338 Should Be Equal As Strings ${resp.status_code} 204 msg=${msg}
341 [Arguments] ${node_id} ${configured_flow_body} ${updating_flow_body}
342 [Documentation] Updates a flow by using update-flow operation. ${xmlroot} is usually a variable created by
343 ... Create Flow Variables For Suite From XML File keyword from this library.
344 Log ${configured_flow_body}
345 Log ${updating_flow_body}
346 ${xml} Parse Xml <input xmlns="urn:opendaylight:flow:service"></input>
348 ${origflow}= Parse Xml ${configured_flow_body}
349 ${updflow}= Parse Xml ${updating_flow_body}
350 Remove Element ${origflow} id clear_tail=True
351 Remove Element ${updflow} id clear_tail=True
352 Remove Element Attribute ${origflow} xmlns
353 Remove Element Attribute ${updflow} xmlns
354 Set Element Tag ${origflow} original-flow
355 Set Element Tag ${updflow} updated-flow
356 Add Element ${xml} ${origflow}
357 Add Element ${xml} ${updflow}
358 Add Element ${xml} <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
359 ${nodeelm}= Get Element ${xml} node
360 Set Element Attribute ${nodeelm} xmlns:inv urn:opendaylight:inventory
362 ${strxml}= Element To String ${xml}
363 ${resp}= RequestsLibrary.Post Request session /restconf/operations/sal-flow:update-flow data=${strxml}
365 Should Be Equal As Strings ${resp.status_code} 200
367 Update Flow Via Restconf
368 [Arguments] ${node_id} ${table_id} ${flow_id} ${flow_body}
369 [Documentation] Updates a flow configuration by given flow details (${node_id}, ${table_id}, ${flow_body}) using PUT method
371 ${resp}= RequestsLibrary.Put Request session ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id} data=${flow_body}
373 ${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.
374 Should Be Equal As Strings ${resp.status_code} 200 msg=${msg}
377 [Arguments] ${node_id} ${xmlroot}
378 [Documentation] Deletes a flow by using remove-flow opearation. ${xmlroot} is usually a variable created by
379 ... Create Flow Variables For Suite From XML File keyword from this library.
380 ${req}= Copy Element ${xmlroot}
381 Remove Element ${req} id clear_tail=True
382 Set Element Tag ${req} input
383 Set Element Attribute ${req} xmlns urn:opendaylight:flow:service
384 Add Element ${req} <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
385 ${nodeelm}= Get Element ${req} node
386 Set Element Attribute ${nodeelm} xmlns:inv urn:opendaylight:inventory
388 ${strxml}= Element To String ${req}
389 ${resp}= RequestsLibrary.Post Request session /restconf/operations/sal-flow:remove-flow data=${strxml}
391 Should Be Equal As Strings ${resp.status_code} 200
393 Delete Flow Via Restconf
394 [Arguments] ${node_id} ${table_id} ${flow_id}
395 [Documentation] Deletes a flow from configuration datastore specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using DELETE method
396 ${resp}= RequestsLibrary.Delete Request session ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id}
398 ${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.
399 Should Be Equal As Strings ${resp.status_code} 200 msg=${msg}