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
8 Library RequestsLibrary
9 Variables ../variables/Variables.py
14 Check Flow Stats Are Available
15 [Arguments] ${node_id} ${flows}
16 [Documentation] A GET on the /node/${node_id} inventory API is made and flow stats string is checked for existence.
17 ${resp} RequestsLibrary.Get Request session ${OPERATIONAL_NODES_API}/node/${node_id}/table/2
19 Should Be Equal As Strings ${resp.status_code} 200
20 Should Contain X Times ${resp.content} packet-count ${flows}
23 [Documentation] Calls FlowLib.Make_Inventory_Flow function and initializes and sanitizes
24 ... the basic flow elements that can be given to flow:inventory
25 ${flow}= Make Inventory Flow
29 [Documentation] Used for creating an object that will use an XML format that
30 ... can be given to flow:service.
31 ${flow}= Make Service Flow
34 Set "${flow}" "${property}" With "${property_val}"
35 [Documentation] Embedded variables to make higher level keywords more readable.
36 ... There are some cases where the python attribute uses an underscore,
37 ... but a hyphen needs to be used. This seems inconsistent, and may need
38 ... to be looked at from the openflow plugin perspective.
40 ... At this point, this library will remove the element ${property} from the
41 ... xml representation of the flow and reset with the given value. \ It's not
42 ... possible, yet, to have multiple elements with the same name. \ That will
43 ... likely be needed in the future.
44 ${property} Run Keyword If "table_id" != "${property}" and "cookie_mask" != "${property}" Replace String ${property} _ -
45 ... ELSE Set Variable ${property}
46 Remove Flow XML Element ${flow} ${property}
47 Add Flow XML Element ${flow} ${property} ${property_val}
48 Set Flow Field ${flow} ${property} ${property_val}
52 [Arguments] ${flow} ${instruction_order} ${action_order} ${action} ${action_val}=${EMPTY}
53 [Documentation] Will remove the instruction element first, then add the proper xml structure
54 ... to implement the action as given in the arguments
55 ##For the case that any of the instruction/apply-actions/action elements are not there we need to add them'
56 Remove Flow XML Element ${flow} instruction
57 Add Flow XML Element ${flow} instruction ${EMPTY} instructions
58 Add Flow XML Element ${flow} order ${instruction_order} instructions/instruction
59 Add Flow XML Element ${flow} apply-actions ${EMPTY} instructions/instruction
60 Add Flow XML Element ${flow} action ${EMPTY} instructions/instruction/apply-actions
61 Add Flow XML Element ${flow} order ${action_order} instructions/instruction/apply-actions/action
62 Add Flow XML Element ${flow} ${action} ${action_val} instructions/instruction/apply-actions/action
65 Set Flow Output Action
66 [Arguments] ${flow} ${instruction_order} ${action_order} ${output_port}
67 Set Flow Action ${flow} ${instruction_order} ${action_order} output-action
68 Add Flow XML Element ${flow} output-node-connector ${output_port} instructions/instruction/apply-actions/action/output-action
71 Set Flow Ethernet Match
72 [Arguments] ${flow} ${match_value_dict}
73 [Documentation] Specific keyword for adding an ethernet match rules where the elements are given
74 ... in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any
75 ... existing ethernet-match elements from the flow before adding
76 Clear Flow Matches ${flow} match/ethernet-match
77 Add Flow XML Element ${flow} ethernet-match ${EMPTY} match
78 ${type}= Get From Dictionary ${match_value_dict} type
79 Add Flow XML Element ${flow} ethernet-type ${EMPTY} match/ethernet-match
80 Add Flow XML Element ${flow} type ${type} match/ethernet-match/ethernet-type
81 ${src}= Get From Dictionary ${match_value_dict} source
82 Add Flow XML Element ${flow} ethernet-source ${EMPTY} match/ethernet-match
83 Add Flow XML Element ${flow} address ${src} match/ethernet-match/ethernet-source
84 ${dst}= Get From Dictionary ${match_value_dict} destination
85 Add Flow XML Element ${flow} ethernet-destination ${EMPTY} match/ethernet-match
86 Add Flow XML Element ${flow} address ${dst} match/ethernet-match/ethernet-destination
90 [Arguments] ${flow} ${match_value_dict}
91 [Documentation] Specific keyword for adding an ipv4 match rules where the elements are given
92 ... in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any
93 ... existing ipv4 match elements from the flow before adding
94 Clear Flow Matches ${flow} match/ipv4-source
95 Clear Flow Matches ${flow} match/ipv4-destination
96 ${src}= Get From Dictionary ${match_value_dict} source
97 Add Flow XML Element ${flow} ipv4-source ${src} match
98 ${dst}= Get From Dictionary ${match_value_dict} destination
99 Add Flow XML Element ${flow} ipv4-destination ${dst} match
104 [Documentation] Will clean out any existing flow actions in the given ${flow} object
105 Remove Flow XML Element ${flow} instructions/instruction
109 [Arguments] ${flow} ${match_element}
110 [Documentation] Will clean out any existing flow matches in the given ${flow} object
111 Remove Flow XML Element ${flow} match/${match_element}
114 Set Flow XML Element Attribute
115 [Arguments] ${flow} ${element} ${id} ${value}
116 [Documentation] Will set the given id/value pair to the given to the element provided
117 ... and make the proper changes to the ${flow} object also provided.
118 ${flow_xml}= Parse XML ${flow.xml}
119 Set Element Attribute ${flow_xml} ${id} ${value} xpath=${element}
120 ${xml_string}= Element To String ${flow_xml}
121 Set Flow Field ${flow} xml ${xml_string}
126 [Arguments] ${flow} ${element} ${element_val}=${EMPTY} ${xpath}=.
127 [Documentation] Will modify the current xml representation of the ${flow} object to contain
128 ... the given ${element} at the given ${xpath}. If the ${element} uses a value, that can be
129 ... passed eith the ${element_val} which defaults to ${EMPTY} if not used. NOTE: since there
130 ... are two default parameters to this keyword, if you have an ${xpath} to use, but no ${element_val}
131 ... you will still need to pass ${EMPTY} when invoking so that ${xpath} will end up at the right
132 ... location in the parameter list
133 ${flow_xml}= Parse XML ${flow.xml}
134 Add Element ${flow_xml} <${element}>${element_val}</${element}> xpath=${xpath}
135 ${xml_string}= Element To String ${flow_xml}
136 Set Flow Field ${flow} xml ${xml_string}
140 Remove Flow XML Element
141 [Arguments] ${flow} ${element_xpath}
142 [Documentation] Removes the element at the given ${element_xpath} within the given ${flow}
143 ... object. The ${flow} object's xml representation will be updated to reflect this removal.
144 ${flow_xml}= Parse XML ${flow.xml}
145 Run Keyword And Ignore Error Remove Elements ${flow_xml} xpath=${element_xpath}
146 ${xml_string}= Element To String ${flow_xml}
147 Set Flow Field ${flow} xml ${xml_string}
150 Add Flow To Controller And Verify
151 [Arguments] ${flow_body} ${node_id} ${table_id} ${flow_id}
152 [Documentation] Push flow through REST-API and verify in data-store
153 ${resp} RequestsLibrary.Put Request session ${REST_CON}/node/${node_id}/table/${table_id}/flow/${flow_id} headers=${HEADERS_XML} data=${flow_body}
155 Should Be Equal As Strings ${resp.status_code} 200
156 ${resp} RequestsLibrary.Get Request session ${REST_CON}/node/${node_id}/table/${table_id}/flow/${flow_id} headers=${ACCEPT_XML}
158 Should Be Equal As Strings ${resp.status_code} 200
159 compare xml ${flow_body} ${resp.content}
161 Verify Flow On Mininet Switch
162 [Arguments] ${flow_elements}
163 [Documentation] Checking flow on switch
165 write dpctl dump-flows -O OpenFlow13
166 ${switchoutput} Read Until >
167 : FOR ${flowElement} IN @{flow_elements}
168 \ should Contain ${switchoutput} ${flowElement}
170 Remove Flow From Controller And Verify
171 [Arguments] ${flow_body} ${node_id} ${table_id} ${flow_id}
172 [Documentation] Remove flow
173 ${resp} RequestsLibrary.Delete Request session ${REST_CON}/node/${node_id}/table/${table_id}/flow/${flow_id}
175 Should Be Equal As Strings ${resp.status_code} 200
176 ${resp} RequestsLibrary.Get Request session ${REST_CON}/node/${node_id}/table/${table_id}
178 Should Not Contain ${resp.content} ${flow_id}
180 Verify Flow Does Not Exist On Mininet Switch
181 [Arguments] ${flow_elements}
182 [Documentation] Checking flow on switch is removed
184 write dpctl dump-flows -O OpenFlow13
185 ${switchoutput} Read Until >
186 : FOR ${flowElement} IN @{flow_elements}
187 \ should Not Contain ${switchoutput} ${flowElement}
190 [Arguments] ${node_id}
191 [Documentation] Removes any flows considered "default". one such flow is
192 ... to forward all traffic to the CONTROLLER with priority 0 at flow-table 0
193 ... If/When others are implemented this keyword can be updated to include those.
194 ${flow}= Make Service Flow
195 Set "${flow}" "priority" With "0"
196 Set "${flow}" "flow-table" With "0"
197 Add Flow XML Element ${flow} node /inv:nodes/inv:node[inv:id="${node_id}"]
198 Set Flow XML Element Attribute ${flow} node xmlns:inv urn:opendaylight:inventory
199 Log Flow XML is ${flow.xml}
200 write dpctl dump-flows -O OpenFlow13
201 ${switchoutput} Read Until >
202 ${headers}= Create Dictionary Content-Type=application/yang.data+xml
203 ${resp} RequestsLibrary.Post Request session restconf/operations/sal-flow:remove-flow data=${flow.xml} headers=${headers}
205 Should Be Equal As Strings ${resp.status_code} 200
206 ${resp}= RequestsLibrary.Get Request session ${OPERATIONAL_NODES_API}
208 Should Not Contain ${resp.content} "output-node-connector": "CONTROLLER",
209 ${strings_to_check_for}= Create List CONTROLLER
210 Verify Flow Does Not Exist On Mininet Switch ${strings_to_check_for}
212 Create Flow Variables For Suite From XML File
214 [Documentation] Given the flow XML ${file}, it will create several suite wide variables
215 ${data}= OperatingSystem.Get File ${file}
216 ${xmlroot}= Parse Xml ${file}
217 ${table_id}= Get Element Text ${xmlroot} table_id
218 ${flow_id}= Get Element Text ${xmlroot} id
219 ${flow_priority}= Get Element Text ${xmlroot} priority
220 ${upddata}= Get Data For Flow Put Update ${data}
221 Set Suite Variable ${table_id}
222 Set Suite Variable ${flow_id}
223 Set Suite Variable ${flow_priority}
224 Set Suite Variable ${data}
225 Set Suite Variable ${upddata}
226 Set Suite Variable ${xmlroot}
228 Check Datastore Presence
229 [Arguments] ${fname} ${reqconfpres} ${reqoperpres} ${upd}
230 [Documentation] Checks if flow is properly existing or not existing in the config and operational
231 ... datastores, based on the variables ${reqconfpres} and ${reqoperpres}
232 Create Flow Variables For Suite From XML File ${XmlsDir}/${fname}
233 # Note: ${upddata} and ${data} are suite variables set by the keyword above.
234 ${det}= Set Variable If ${upd}==${True} ${upddata} ${data}
235 Check Config Flow ${reqconfpres} ${det}
236 Check Operational Flow ${reqoperpres} ${det}
238 Flow Presence In Config Store
239 [Arguments] ${expvalue}
240 [Documentation] Checks the config store for given flow. Returns True if present, otherwise returns False
241 ... This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx}
242 ${headers}= Create Dictionary Accept=application/xml
243 ${resp}= RequestsLibrary.Get Request session ${CONFIG_NODES_API}/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id} headers=${headers}
246 Return From Keyword If ${resp.status_code}!=200 ${False} ${EMPTY}
247 ${pres} ${msg}= Is Flow Configured ${expvalue} ${resp.content}
248 Run Keyword If '''${msg}'''!='${EMPTY}' Log ${msg}
249 Return From Keyword ${pres} ${msg}
251 Flow Presence In Operational Store
252 [Arguments] ${expvalue}
253 [Documentation] Checks the operational store for given flow. Returns True if present, otherwise returns False
254 ... This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx}
255 ${headers}= Create Dictionary Accept=application/xml
256 ${resp}= RequestsLibrary.Get Request session ${OPERATIONAL_NODES_API}/node/openflow:${switch_idx}/table/${table_id} headers=${headers}
259 Return From Keyword If ${resp.status_code}!=200 ${False} ${EMPTY}
260 ${pres} ${msg}= Is Flow Operational2 ${expvalue} ${resp.content}
261 Run Keyword If '''${msg}'''!='${EMPTY}' Log ${msg}
262 Return From Keyword ${pres} ${msg}
264 Get Presence Failure Message
265 [Arguments] ${ds} ${expected} ${presence} ${diffmsg}
266 [Documentation] Utility keyword to help manipulate mesage strings that may be used later to PASS or FAIL with
267 Return From Keyword If '''${diffmsg}'''!='${EMPTY}' Flow found in ${ds} data store but: ${diffmsg}
268 ${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
269 ${msgp}= Set Variable If ${presence}==${True} it is present. it is not present.
270 Return From Keyword ${msgf} ${msgp}
273 [Arguments] ${expected} ${expvalue}
274 [Documentation] Wrapper keyword that calls "Flow Presence In Config Store" and "Get Presence Failure Message" from this library
275 ... to verify that the ${expvalue} flow is or is not found in the config store, depending on whether or not it was ${expected}
276 ${presence_flow} ${msg}= Flow Presence In Config Store ${expvalue}
277 ${msgf}= Get Presence Failure Message config ${expected} ${presence_flow} ${msg}
278 Should Be Equal ${expected} ${presence_flow} msg=${msgf}
280 Check Operational Flow
281 [Arguments] ${expected} ${expvalue}
282 [Documentation] Wrapper keyword that calls "Flow Presence In Operational Store" and "Get Presence Failure Message" from this library
283 ... to verify that the ${expvalue} flow is or is not found in the config store, depending on whether or not it was ${expected}
284 ${presence_table} ${msg}= Flow Presence In Operational Store ${expvalue}
285 ${msgf}= Get Presence Failure Message operational ${expected} ${presence_table} ${msg}
286 Should Be Equal ${expected} ${presence_table} msg=${msgf}
289 [Arguments] ${node_id} ${xmlroot}
290 [Documentation] Deploys a flow specified by given flow details (${node_id}, ${xmlroot}) using add-flow operation.
291 ... ${xmlroot} is an xml object of parser xml flow details, usually created by Create Flow Variables For Suite From XML File
292 ... keyword from this library.
293 ${req}= Copy Element ${xmlroot}
294 Remove Element ${req} id clear_tail=True
295 Set Element Tag ${req} input
296 Set Element Attribute ${req} xmlns urn:opendaylight:flow:service
297 Add Element ${req} <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
298 ${nodeelm}= Get Element ${req} node
299 Set Element Attribute ${nodeelm} xmlns:inv urn:opendaylight:inventory
301 ${strxml}= Element To String ${req}
302 ${resp}= RequestsLibrary.Post Request session /restconf/operations/sal-flow:add-flow data=${strxml}
304 Should Be Equal As Strings ${resp.status_code} 200
306 Add Flow Via Restconf
307 [Arguments] ${node_id} ${table_id} ${flow_body}
308 [Documentation] Configures a flow specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using POST method
310 ${resp}= RequestsLibrary.Post Request session ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id} data=${flow_body}
312 ${msg}= Set Variable Adding flow for ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id} failed, http response ${resp.status_code} received.
313 Should Be Equal As Strings ${resp.status_code} 204 msg=${msg}
316 [Arguments] ${node_id} ${configured_flow_body} ${updating_flow_body}
317 [Documentation] Updates a flow by using update-flow operation. ${xmlroot} is usually a variable created by
318 ... Create Flow Variables For Suite From XML File keyword from this library.
319 Log ${configured_flow_body}
320 Log ${updating_flow_body}
321 ${xml} Parse Xml <input xmlns="urn:opendaylight:flow:service"></input>
323 ${origflow}= Parse Xml ${configured_flow_body}
324 ${updflow}= Parse Xml ${updating_flow_body}
325 Remove Element ${origflow} id clear_tail=True
326 Remove Element ${updflow} id clear_tail=True
327 Remove Element Attribute ${origflow} xmlns
328 Remove Element Attribute ${updflow} xmlns
329 Set Element Tag ${origflow} original-flow
330 Set Element Tag ${updflow} updated-flow
331 Add Element ${xml} ${origflow}
332 Add Element ${xml} ${updflow}
333 Add Element ${xml} <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
334 ${nodeelm}= Get Element ${xml} node
335 Set Element Attribute ${nodeelm} xmlns:inv urn:opendaylight:inventory
337 ${strxml}= Element To String ${xml}
338 ${resp}= RequestsLibrary.Post Request session /restconf/operations/sal-flow:update-flow data=${strxml}
340 Should Be Equal As Strings ${resp.status_code} 200
342 Update Flow Via Restconf
343 [Arguments] ${node_id} ${table_id} ${flow_id} ${flow_body}
344 [Documentation] Updates a flow configuration by given flow details (${node_id}, ${table_id}, ${flow_body}) using PUT method
346 ${resp}= RequestsLibrary.Put Request session ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id} data=${flow_body}
348 ${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.
349 Should Be Equal As Strings ${resp.status_code} 200 msg=${msg}
352 [Arguments] ${node_id} ${xmlroot}
353 [Documentation] Deletes a flow by using remove-flow opearation. ${xmlroot} is usually a variable created by
354 ... Create Flow Variables For Suite From XML File keyword from this library.
355 ${req}= Copy Element ${xmlroot}
356 Remove Element ${req} id clear_tail=True
357 Set Element Tag ${req} input
358 Set Element Attribute ${req} xmlns urn:opendaylight:flow:service
359 Add Element ${req} <node>/inv:nodes/inv:node[inv:id="openflow:${node_id}"]</node>
360 ${nodeelm}= Get Element ${req} node
361 Set Element Attribute ${nodeelm} xmlns:inv urn:opendaylight:inventory
363 ${strxml}= Element To String ${req}
364 ${resp}= RequestsLibrary.Post Request session /restconf/operations/sal-flow:remove-flow data=${strxml}
366 Should Be Equal As Strings ${resp.status_code} 200
368 Delete Flow Via Restconf
369 [Arguments] ${node_id} ${table_id} ${flow_id}
370 [Documentation] Deletes a flow from configuration datastore specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using DELETE method
371 ${resp}= RequestsLibrary.Delete Request session ${CONFIG_NODES_API}/node/openflow:${node_id}/table/${table_id}/flow/${flow_id}
373 ${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.
374 Should Be Equal As Strings ${resp.status_code} 200 msg=${msg}