Fix bug in ip -> hypervisor retrieval
[integration/test.git] / csit / libraries / OpenStackOperations.robot
1 *** Settings ***
2 Documentation     Openstack library. This library is useful for tests to create network, subnet, router and vm instances
3 Library           Collections
4 Library           OperatingSystem
5 Library           RequestsLibrary
6 Library           SSHLibrary
7 Resource          DataModels.robot
8 Resource          DevstackUtils.robot
9 Resource          L2GatewayOperations.robot
10 Resource          SetupUtils.robot
11 Resource          SSHKeywords.robot
12 Resource          Utils.robot
13 Resource          ../variables/Variables.robot
14 Resource          ../variables/netvirt/Variables.robot
15 Variables         ../variables/netvirt/Modules.py
16
17 *** Keywords ***
18 Get Tenant ID From Security Group
19     [Documentation]    Returns tenant ID by reading it from existing default security-group.
20     ${rc}    ${output}=    Run And Return Rc And Output    openstack security group show default | grep "| tenant_id" | awk '{print $4}'
21     Should Be True    '${rc}' == '0'
22     [Return]    ${output}
23
24 Get Tenant ID From Network
25     [Arguments]    ${network_uuid}
26     [Documentation]    Returns tenant ID by reading it from existing network.
27     ${resp}=    Get_From_Uri    uri=${CONFIG_API}/neutron:neutron/networks/network/${network_uuid}/    accept=${ACCEPT_EMPTY}    session=session
28     ${tenant_id}=    Utils.Extract Value From Content    ${resp}    /network/0/tenant-id    strip
29     [Return]    ${tenant_id}
30
31 Create Network
32     [Arguments]    ${network_name}    ${additional_args}=${EMPTY}    ${verbose}=TRUE
33     [Documentation]    Create Network with neutron request.
34     ${rc}    ${output}=    Run And Return Rc And Output    openstack network create ${network_name} ${additional_args}
35     Log    ${output}
36     Should Be True    '${rc}' == '0'
37     [Return]    ${output}
38
39 Update Network
40     [Arguments]    ${network_name}    ${additional_args}=${EMPTY}
41     [Documentation]    Update Network with neutron request.
42     ${cmd}=    Set Variable If    '${OPENSTACK_BRANCH}'=='stable/newton'    neutron -v net-update ${network_name} ${additional_args}    openstack network set ${network_name} ${additional_args}
43     ${rc}    ${output}=    Run And Return Rc And Output    ${cmd}
44     Log    ${output}
45     Should Be True    '${rc}' == '0'
46     [Return]    ${output}
47
48 Show Network
49     [Arguments]    ${network_name}
50     [Documentation]    Show Network with neutron request.
51     ${rc}    ${output}=    Run And Return Rc And Output    openstack network show ${network_name}
52     Log    ${output}
53     Should Be True    '${rc}' == '0'
54     [Return]    ${output}
55
56 List Networks
57     [Documentation]    List networks and return output with neutron client.
58     ${rc}    ${output}=    Run And Return Rc And Output    openstack network list
59     Log    ${output}
60     Should Be True    '${rc}' == '0'
61     [Return]    ${output}
62
63 List Subnets
64     [Documentation]    List subnets and return output with neutron client.
65     ${rc}    ${output}=    Run And Return Rc And Output    openstack subnet list
66     Log    ${output}
67     Should Be True    '${rc}' == '0'
68     [Return]    ${output}
69
70 Delete Network
71     [Arguments]    ${network_name}
72     [Documentation]    Delete Network with neutron request.
73     ${rc}    ${output}=    Run And Return Rc And Output    openstack network delete ${network_name}
74     Log    ${output}
75     Should Be True    '${rc}' == '0'
76
77 Create SubNet
78     [Arguments]    ${network_name}    ${subnet}    ${range_ip}    ${additional_args}=${EMPTY}
79     [Documentation]    Create SubNet for the Network with neutron request.
80     ${rc}    ${output}=    Run And Return Rc And Output    openstack subnet create --network ${network_name} --subnet-range ${range_ip} ${subnet} ${additional_args}
81     Log    ${output}
82     Should Be True    '${rc}' == '0'
83
84 Update SubNet
85     [Arguments]    ${subnet_name}    ${additional_args}=${EMPTY}
86     [Documentation]    Update subnet with neutron request.
87     ${cmd}=    Set Variable If    '${OPENSTACK_BRANCH}'=='stable/newton'    neutron -v subnet-update ${subnet_name} ${additional_args}    openstack subnet set ${subnet_name} ${additional_args}
88     ${rc}    ${output}=    Run And Return Rc And Output    ${cmd}
89     Log    ${output}
90     Should Be True    '${rc}' == '0'
91     [Return]    ${output}
92
93 Show SubNet
94     [Arguments]    ${subnet_name}
95     [Documentation]    Show subnet with neutron request.
96     ${rc}    ${output}=    Run And Return Rc And Output    openstack subnet show ${subnet_name}
97     Log    ${output}
98     Should Be True    '${rc}' == '0'
99     [Return]    ${output}
100
101 Create Port
102     [Arguments]    ${network_name}    ${port_name}    ${sg}=default    ${additional_args}=${EMPTY}    ${allowed_address_pairs}=${EMPTY}
103     [Documentation]    Create Port with neutron request.
104     # if allowed_address_pairs is not empty we need to create the arguments to pass to the port create command. They are
105     # in a different format with the neutron vs openstack cli.
106     ${address_pair_length}=    Get Length    ${allowed_address_pairs}
107     ${allowed_pairs_argv}=    Set Variable If    '${OPENSTACK_BRANCH}'=='stable/newton' and '${address_pair_length}'=='2'    --allowed-address-pairs type=dict list=true ip_address=@{allowed_address_pairs}[0] ip_address=@{allowed_address_pairs}[1]
108     ${allowed_pairs_argv}=    Set Variable If    '${OPENSTACK_BRANCH}'!='stable/newton' and '${address_pair_length}'=='2'    --allowed-address ip-address=@{allowed_address_pairs}[0] --allowed-address ip-address=@{allowed_address_pairs}[1]    ${allowed_pairs_argv}
109     ${allowed_pairs_argv}=    Set Variable If    '${address_pair_length}'=='0'    ${EMPTY}    ${allowed_pairs_argv}
110     ${cmd}=    Set Variable If    '${OPENSTACK_BRANCH}'=='stable/newton'    neutron -v port-create ${network_name} --name ${port_name} --security-group ${sg} ${additional_args} ${allowed_pairs_argv}    openstack port create --network ${network_name} ${port_name} --security-group ${sg} ${additional_args} ${allowed_pairs_argv}
111     ${rc}    ${output}=    Run And Return Rc And Output    ${cmd}
112     Log    ${output}
113     Should Be True    '${rc}' == '0'
114
115 Update Port
116     [Arguments]    ${port_name}    ${additional_args}=${EMPTY}
117     [Documentation]    Update port with neutron request.
118     ${rc}    ${output}=    Run And Return Rc And Output    openstack port set ${port_name} ${additional_args}
119     Log    ${output}
120     Should Be True    '${rc}' == '0'
121     [Return]    ${output}
122
123 Show Port
124     [Arguments]    ${port_name}
125     [Documentation]    Show port with neutron request.
126     ${rc}    ${output}=    Run And Return Rc And Output    openstack port show ${port_name}
127     Log    ${output}
128     Should Be True    '${rc}' == '0'
129     [Return]    ${output}
130
131 Delete Port
132     [Arguments]    ${port_name}
133     [Documentation]    Delete Port with neutron request.
134     ${rc}    ${output}=    Run And Return Rc And Output    openstack port delete ${port_name}
135     Log    ${output}
136     Should Be True    '${rc}' == '0'
137
138 List Ports
139     [Documentation]    List ports and return output with neutron client.
140     ${rc}    ${output}=    Run And Return Rc And Output    openstack port list
141     Log    ${output}
142     Should Be True    '${rc}' == '0'
143     [Return]    ${output}
144
145 List Nova VMs
146     [Documentation]    List VMs and return output with nova client.
147     ${rc}    ${output}=    Run And Return Rc And Output    openstack server list --all-projects
148     Log    ${output}
149     Should Be True    '${rc}' == '0'
150     [Return]    ${output}
151
152 Create And Associate Floating IPs
153     [Arguments]    ${external_net}    @{vm_list}
154     [Documentation]    Create and associate floating IPs to VMs with nova request
155     ${ip_list}=    Create List    @{EMPTY}
156     : FOR    ${vm}    IN    @{vm_list}
157     \    ${rc}    ${output}=    Run And Return Rc And Output    openstack floating ip create ${external_net}
158     \    Log    ${output}
159     \    Should Be True    '${rc}' == '0'
160     \    @{ip}    Get Regexp Matches    ${output}    [0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}
161     \    ${ip_length}    Get Length    ${ip}
162     \    Run Keyword If    ${ip_length}>0    Append To List    ${ip_list}    @{ip}[0]
163     \    ...    ELSE    Append To List    ${ip_list}    None
164     \    ${rc}    ${output}=    Run And Return Rc And Output    openstack server add floating ip ${vm} @{ip}[0]
165     \    Log    ${output}
166     \    Should Be True    '${rc}' == '0'
167     [Return]    ${ip_list}
168
169 Delete Floating IP
170     [Arguments]    ${fip}
171     [Documentation]    Delete floating ip with neutron request.
172     ${rc}    ${output}=    Run And Return Rc And Output    openstack floating ip delete ${fip}
173     Log    ${output}
174     Should Be True    '${rc}' == '0'
175
176 Verify Gateway Ips
177     [Documentation]    Verifies the Gateway Ips with dump flow.
178     ${output}=    Write Commands Until Prompt And Log    sudo ovs-ofctl -O OpenFlow13 dump-flows br-int
179     : FOR    ${GatewayIpElement}    IN    @{GATEWAY_IPS}
180     \    Should Contain    ${output}    ${GatewayIpElement}
181
182 Verify Dhcp Ips
183     [Documentation]    Verifies the Dhcp Ips with dump flow.
184     ${output}=    Write Commands Until Prompt And Log    sudo ovs-ofctl -O OpenFlow13 dump-flows br-int
185     : FOR    ${DhcpIpElement}    IN    @{DHCP_IPS}
186     \    Should Contain    ${output}    ${DhcpIpElement}
187
188 Verify No Dhcp Ips
189     [Documentation]    Verifies the Dhcp Ips with dump flow.
190     ${output}=    Write Commands Until Prompt And Log    sudo ovs-ofctl -O OpenFlow13 dump-flows br-int
191     : FOR    ${DhcpIpElement}    IN    @{DHCP_IPS}
192     \    Should Not Contain    ${output}    ${DhcpIpElement}
193
194 Delete SubNet
195     [Arguments]    ${subnet}
196     [Documentation]    Delete SubNet for the Network with neutron request.
197     Log    ${subnet}
198     ${rc}    ${output}=    Run And Return Rc And Output    openstack subnet delete ${subnet}
199     Should Be True    '${rc}' == '0'
200
201 Verify No Gateway Ips
202     [Documentation]    Verifies the Gateway Ips removed with dump flow.
203     ${output}=    Write Commands Until Prompt And Log    sudo ovs-ofctl -O OpenFlow13 dump-flows br-int
204     : FOR    ${GatewayIpElement}    IN    @{GATEWAY_IPS}
205     \    Should Not Contain    ${output}    ${GatewayIpElement}
206
207 Delete Vm Instance
208     [Arguments]    ${vm_name}
209     [Documentation]    Delete Vm instances using instance names.
210     ${rc}    ${output}=    Run And Return Rc And Output    openstack server delete ${vm_name}
211     Log    ${output}
212
213 Get Net Id
214     [Arguments]    ${network_name}
215     [Documentation]    Retrieve the net id for the given network name to create specific vm instance
216     ${rc}    ${output}=    Run And Return Rc And Output    openstack network list | grep "${network_name}" | awk '{print $2}'
217     Should Be True    '${rc}' == '0'
218     ${splitted_output}=    Split String    ${output}    ${EMPTY}
219     ${net_id}=    Get from List    ${splitted_output}    0
220     [Return]    ${net_id}
221
222 Get Subnet Id
223     [Arguments]    ${subnet_name}
224     [Documentation]    Retrieve the subnet id for the given subnet name
225     ${rc}    ${output}=    Run And Return Rc And Output    openstack subnet show "${subnet_name}" | grep " id " | awk '{print $4}'
226     Should Be True    '${rc}' == '0'
227     ${splitted_output}=    Split String    ${output}    ${EMPTY}
228     ${subnet_id}=    Get from List    ${splitted_output}    0
229     [Return]    ${subnet_id}
230
231 Get Port Id
232     [Arguments]    ${port_name}
233     [Documentation]    Retrieve the port id for the given port name to attach specific vm instance to a particular port
234     ${rc}    ${output}=    Run And Return Rc And Output    openstack port list | grep "${port_name}" | awk '{print $2}'
235     Should Be True    '${rc}' == '0'
236     ${splitted_output}=    Split String    ${output}    ${EMPTY}
237     ${port_id}=    Get from List    ${splitted_output}    0
238     [Return]    ${port_id}
239
240 Get Router Id
241     [Arguments]    ${router1}
242     [Documentation]    Retrieve the router id for the given router name
243     ${rc}    ${output}=    Run And Return Rc And Output    openstack router list -f table | grep "${router1}" | awk '{print $2}'
244     Should Be True    '${rc}' == '0'
245     ${splitted_output}=    Split String    ${output}    ${EMPTY}
246     ${router_id}=    Get from List    ${splitted_output}    0
247     [Return]    ${router_id}
248
249 Create Vm Instances
250     [Arguments]    ${net_name}    ${vm_instance_names}    ${image}=${EMPTY}    ${flavor}=m1.nano    ${sg}=default    ${min}=1
251     ...    ${max}=1
252     [Documentation]    Create X Vm Instance with the net id of the Netowrk.
253     ${image}    Set Variable If    "${image}"=="${EMPTY}"    ${CIRROS_${OPENSTACK_BRANCH}}    ${image}
254     ${net_id}=    Get Net Id    ${net_name}
255     : FOR    ${VmElement}    IN    @{vm_instance_names}
256     \    ${rc}    ${output}=    Run And Return Rc And Output    openstack server create --image ${image} --flavor ${flavor} --nic net-id=${net_id} ${VmElement} --security-group ${sg} --min ${min} --max ${max}
257     \    Should Be True    '${rc}' == '0'
258     \    Log    ${output}
259
260 Create Vm Instance With Port
261     [Arguments]    ${port_name}    ${vm_instance_name}    ${image}=${EMPTY}    ${flavor}=m1.nano    ${sg}=default
262     [Documentation]    Create One VM instance using given ${port_name} and for given ${compute_node}
263     ${image}    Set Variable If    "${image}"=="${EMPTY}"    ${CIRROS_${OPENSTACK_BRANCH}}    ${image}
264     ${port_id}=    Get Port Id    ${port_name}
265     ${rc}    ${output}=    Run And Return Rc And Output    openstack server create --image ${image} --flavor ${flavor} --nic port-id=${port_id} ${vm_instance_name} --security-group ${sg}
266     Log    ${output}
267
268 Create Vm Instance With Ports
269     [Arguments]    ${port_name}    ${port2_name}    ${vm_instance_name}    ${image}=${EMPTY}    ${flavor}=m1.nano    ${sg}=default
270     [Documentation]    Create One VM instance using given ${port_name} and for given ${compute_node}
271     ${image}    Set Variable If    "${image}"=="${EMPTY}"    ${CIRROS_${OPENSTACK_BRANCH}}    ${image}
272     ${port_id}=    Get Port Id    ${port_name}
273     ${port2_id}=    Get Port Id    ${port2_name}
274     ${rc}    ${output}=    Run And Return Rc And Output    openstack server create --image ${image} --flavor ${flavor} --nic port-id=${port_id} --nic port-id=${port2_id} ${vm_instance_name} --security-group ${sg}
275     Log    ${output}
276     Should Be True    '${rc}' == '0'
277
278 Create Vm Instance With Port On Compute Node
279     [Arguments]    ${port_name}    ${vm_instance_name}    ${compute_node}    ${image}=${EMPTY}    ${flavor}=m1.nano    ${sg}=default
280     [Documentation]    Create One VM instance using given ${port_name} and for given ${compute_node}
281     ${image}    Set Variable If    "${image}"=="${EMPTY}"    ${CIRROS_${OPENSTACK_BRANCH}}    ${image}
282     ${port_id}=    Get Port Id    ${port_name}
283     ${hostname_compute_node}=    Get Hypervisor Hostname From IP    ${compute_node}
284     ${rc}    ${output}=    Run And Return Rc And Output    openstack server create --image ${image} --flavor ${flavor} --nic port-id=${port_id} --security-group ${sg} --availability-zone nova:${hostname_compute_node} ${vm_instance_name}
285     Log    ${output}
286     Should Be True    '${rc}' == '0'
287
288 Get Hypervisor Hostname From IP
289     [Arguments]    ${hypervisor_ip}
290     [Documentation]    Returns the hostname found for the given IP address if it's listed in hypervisor list. For debuggability
291     ...    the full listing is logged first, then followed by a grep | cut to focus on the actual hostname to return
292     ${rc}    ${output}    Run And Return Rc And Output    openstack hypervisor list
293     Log    ${output}
294     ${rc}    ${hostname}=    Run And Return Rc And Output    openstack hypervisor list -f value | grep "${hypervisor_ip} " | cut -d" " -f 2
295     Log    ${hostname}
296     Should Be True    '${rc}' == '0'
297     [Return]    ${hostname}
298
299 Create Nano Flavor
300     [Documentation]    Create a nano flavor
301     ${rc}    ${output}=    Run And Return Rc And Output    openstack flavor create m1.nano --id auto --ram 64 --disk 0 --vcpus 1
302     Log    ${output}
303     Should Be True    '${rc}' == '0'
304
305 Verify VM Is ACTIVE
306     [Arguments]    ${vm_name}
307     [Documentation]    Run these commands to check whether the created vm instance is active or not.
308     ${rc}    ${output}=    Run And Return Rc And Output    openstack server show ${vm_name} | grep OS-EXT-STS:vm_state
309     Should Be True    '${rc}' == '0'
310     Should Contain    ${output}    active
311
312 Poll VM Is ACTIVE
313     [Arguments]    ${vm_name}    ${retry}=600s    ${retry_interval}=30s
314     [Documentation]    Run these commands to check whether the created vm instance is active or not.
315     Wait Until Keyword Succeeds    ${retry}    ${retry_interval}    Verify VM Is ACTIVE    ${vm_name}
316
317 Collect VM IP Addresses
318     [Arguments]    ${fail_on_none}    @{vm_list}
319     [Documentation]    Using the console-log on the provided ${vm_list} to search for the string "obtained" which
320     ...    correlates to the instance receiving it's IP address via DHCP. Also retrieved is the ip of the nameserver
321     ...    if available in the console-log output. The keyword will also return a list of the learned ips as it
322     ...    finds them in the console log output, and will have "None" for Vms that no ip was found.
323     ${ip_list}    Create List    @{EMPTY}
324     : FOR    ${vm}    IN    @{vm_list}
325     \    ${rc}    ${vm_ip_line}=    Run And Return Rc And Output    openstack console log show ${vm} | grep -i "obtained"
326     \    @{vm_ip}    Get Regexp Matches    ${vm_ip_line}    [0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}
327     \    ${vm_ip_length}    Get Length    ${vm_ip}
328     \    Run Keyword If    ${vm_ip_length}>0    Append To List    ${ip_list}    @{vm_ip}[0]
329     \    ...    ELSE    Append To List    ${ip_list}    None
330     \    ${rc}    ${dhcp_ip_line}=    Run And Return Rc And Output    openstack console log show ${vm} | grep "^nameserver"
331     \    ${dhcp_ip}    Get Regexp Matches    ${dhcp_ip_line}    [0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}
332     \    ${dhcp_ip_length}    Get Length    ${dhcp_ip}
333     \    Run Keyword If    ${dhcp_ip_length}<=0    Append To List    ${dhcp_ip}    None
334     \    ${vm_console_output}=    Run    openstack console log show ${vm}
335     \    Log    ${vm_console_output}
336     ${dhcp_length}    Get Length    ${dhcp_ip}
337     Run Keyword If    '${fail_on_none}' == 'true'    Should Not Contain    ${ip_list}    None
338     Run Keyword If    '${fail_on_none}' == 'true'    Should Not Contain    ${dhcp_ip}    None
339     Should Be True    ${dhcp_length} <= 1
340     Return From Keyword If    ${dhcp_length}==0    ${ip_list}    ${EMPTY}
341     [Return]    ${ip_list}    ${dhcp_ip}
342
343 Get Match
344     [Arguments]    ${text}    ${regexp}    ${index}=0
345     [Documentation]    Wrapper around Get Regexp Matches to return None if not found or the first match if found.
346     @{matches} =    String.Get Regexp Matches    ${text}    ${regexp}
347     ${matches_length} =    Get Length    ${matches}
348     BuiltIn.Set Suite Variable    ${OS_MATCH}    None
349     BuiltIn.Run Keyword If    ${matches_length} > ${index}    BuiltIn.Set Suite Variable    ${OS_MATCH}    @{matches}[${index}]
350     [Return]    ${OS_MATCH}
351
352 Get VM IP
353     [Arguments]    ${fail_on_none}    ${vm}
354     [Documentation]    Get the vm ip address and nameserver by scraping the vm's console log.
355     ...    Get VM IP returns three values: [0] the vm IP, [1] the DHCP IP and [2] the vm console log.
356     ${rc}    ${vm_console_output}=    Run And Return Rc And Output    openstack console log show ${vm}
357     ${vm_ip} =    Set Variable    None
358     ${dhcp_ip} =    Set Variable    None
359     ${match} =    Get Match    ${vm_console_output}    ${REGEX_OBTAINED}
360     ${vm_ip} =    Get Match    ${match}    ${REGEX_IPV4}    0
361     ${match} =    Get Match    ${vm_console_output}    ${REGEX_IPROUTE}
362     ${dhcp_ip} =    Get Match    ${match}    ${REGEX_IPV4}    1
363     BuiltIn.Run Keyword If    '${fail_on_none}' == 'true'    Should Not Contain    ${vm_ip}    None
364     BuiltIn.Run Keyword If    '${fail_on_none}' == 'true'    Should Not Contain    ${dhcp_ip}    None
365     [Return]    ${vm_ip}    ${dhcp_ip}    ${vm_console_output}
366
367 Get VM IPs
368     [Arguments]    @{vms}
369     [Documentation]    Get the instance IP addresses and nameserver address for the list of given vms.
370     ...    First poll for the vm instance to be in the active state, then poll for the vm ip address and nameserver.
371     ...    Get VM IPs returns two things: [0] a list of the ips for the vms passed to this keyword (may contain values
372     ...    of None) and [1] the dhcp ip address found in the last vm checked.
373     ...    TODO: there is a potential issue for a caller that passes in VMs belonging to different networks that
374     ...    may have different dhcp server addresses. Not sure what TODO about that, but noting it here for reference.
375     @{vm_ips}    BuiltIn.Create List    @{EMPTY}
376     : FOR    ${vm}    IN    @{vms}
377     \    Poll VM Is ACTIVE    ${vm}
378     \    ${status}    ${ips_and_console_log}    Run Keyword And Ignore Error    Wait Until Keyword Succeeds    180s    15s
379     \    ...    Get VM IP    true    ${vm}
380     \    # If there is trouble with Get VM IP, the status will be FAIL and the return value will be a string of what went
381     \    # wrong. We need to handle both the PASS and FAIL cases. In the FAIL case we know we wont have access to the
382     \    # console log, as it would not be returned; so we need to grab it again to log it. We also can append 'None' to
383     \    # the vm ip list if status is FAIL.
384     \    Run Keyword If    "${status}" == "PASS"    BuiltIn.Log    ${ips_and_console_log[2]}
385     \    BuiltIn.Run Keyword If    "${status}" == "PASS"    Collections.Append To List    ${vm_ips}    ${ips_and_console_log[0]}
386     \    BuiltIn.Run Keyword If    "${status}" == "FAIL"    Collections.Append To List    ${vm_ips}    None
387     \    ${rc}    ${vm_console_output}=    BuiltIn.Run Keyword If    "${status}" == "FAIL"    Run And Return Rc And Output    openstack console log show ${vm}
388     \    BuiltIn.Run Keyword If    "${status}" == "FAIL"    BuiltIn.Log    ${vm_console_output}
389     Copy DHCP Files From Control Node
390     [Return]    @{vm_ips}    ${ips_and_console_log[1]}
391
392 Collect VM IPv6 SLAAC Addresses
393     [Arguments]    ${fail_on_none}    ${prefix}    @{vm_list}
394     [Documentation]    Using the console-log on the provided ${vm_list} to search for the string "inet6" which
395     ...    correlates to the instance generated IPv6 address, based on the ${prefix} received from ODL (SLAAC mode).
396     ${ip_list}    Create List    @{EMPTY}
397     : FOR    ${vm}    IN    @{vm_list}
398     \    Log    ${vm}
399     \    ${rc}    ${vm_ip_line}=    Run And Return Rc And Output    openstack console log show ${vm} | grep -i "inet6"
400     \    Log    ${vm_ip_line}
401     \    Log    ${rc}
402     \    @{vm_ip_list}    Get Regexp Matches    ${vm_ip_line}    ${prefix}
403     \    ${vm_ip_length}    Get Length    ${vm_ip_list}
404     \    Run Keyword If    ${vm_ip_length}>0    Append To List    ${ip_list}    @{vm_ip_list}[0]
405     \    ...    ELSE    Append To List    ${ip_list}    None
406     \    Log    ${ip_list}
407     Run Keyword If    '${fail_on_none}' == 'true'    Should Not Contain    ${ip_list}    None
408     Log    ${ip_list}
409     [Return]    ${ip_list}
410
411 View Vm Console
412     [Arguments]    ${vm_instance_names}
413     [Documentation]    View Console log of the created vm instances using nova show.
414     : FOR    ${VmElement}    IN    @{vm_instance_names}
415     \    ${rc}    ${output}=    Run And Return Rc And Output    openstack server show ${VmElement}
416     \    Log    ${output}
417     \    Should Be True    '${rc}' == '0'
418     \    ${rc}    ${output}=    Run And Return Rc And Output    openstack console log show ${VmElement}
419     \    Log    ${output}
420     \    Should Be True    '${rc}' == '0'
421
422 Ping Vm From DHCP Namespace
423     [Arguments]    ${net_name}    ${vm_ip}
424     [Documentation]    Reach all Vm Instance with the net id of the Netowrk.
425     Get ControlNode Connection
426     ${net_id}=    Get Net Id    ${net_name}
427     ${output}=    Write Commands Until Prompt And Log    sudo ip netns exec qdhcp-${net_id} ping -c 3 ${vm_ip}    20s
428     Should Contain    ${output}    64 bytes
429
430 Ping From DHCP Should Not Succeed
431     [Arguments]    ${net_name}    ${vm_ip}
432     [Documentation]    Should Not Reach Vm Instance with the net id of the Netowrk.
433     Return From Keyword If    "skip_if_${SECURITY_GROUP_MODE}" in @{TEST_TAGS}
434     Get ControlNode Connection
435     ${net_id}=    Get Net Id    ${net_name}
436     ${output}=    Write Commands Until Prompt And Log    sudo ip netns exec qdhcp-${net_id} ping -c 3 ${vm_ip}    20s
437     Should Not Contain    ${output}    64 bytes
438
439 Ping Vm From Control Node
440     [Arguments]    ${vm_floating_ip}    ${additional_args}=${EMPTY}
441     [Documentation]    Ping VM floating IP from control node
442     Get ControlNode Connection
443     ${output}=    Write Commands Until Prompt And Log    ping ${additional_args} -c 3 ${vm_floating_ip}    20s
444     Should Contain    ${output}    64 bytes
445
446 Curl Metadata Server
447     [Documentation]    Ping to the expected destination ip.
448     ${output}=    Write Commands Until Expected Prompt    curl -i http://169.254.169.254    ${OS_SYSTEM_PROMPT}
449     Write Commands Until Prompt    exit
450     Should Contain    ${output}    200
451
452 Close Vm Instance
453     [Documentation]    Exit the vm instance.
454     ${output}=    Write Commands Until Prompt And Log    exit
455
456 Check If Console Is VmInstance
457     [Arguments]    ${console}=cirros
458     [Documentation]    Check if the session has been able to login to the VM instance
459     ${output}=    Write Commands Until Expected Prompt    id    ${OS_SYSTEM_PROMPT}
460     Should Contain    ${output}    ${console}
461
462 Exit From Vm Console
463     [Documentation]    Check if the session has been able to login to the VM instance and exit the instance
464     ${rcode}=    Run Keyword And Return Status    Check If Console Is VmInstance    cirros
465     Run Keyword If    ${rcode}    Write Commands Until Prompt    exit
466
467 Check Ping
468     [Arguments]    ${ip_address}    ${ttl}=64
469     [Documentation]    Run Ping command on the IP available as argument
470     ${ethertype}=    Get Regexp Matches    ${ip_address}    ${IP_REGEX}
471     ${output}=    Run Keyword If    ${ethertype}    Write Commands Until Expected Prompt    ping -t ${ttl} -c 3 ${ip_address}    ${OS_SYSTEM_PROMPT}
472     ...    ELSE    Write Commands Until Expected Prompt    ping6 -t ${ttl} -c 3 ${ip_address}    ${OS_SYSTEM_PROMPT}
473     Should Contain    ${output}    64 bytes
474
475 Check No Ping
476     [Arguments]    ${ip_address}    ${ttl}=64
477     [Documentation]    Run Ping command to the IP given as argument, executing 3 times and expecting NOT to see "64 bytes"
478     ${output}=    Write Commands Until Expected Prompt    ping -t ${ttl} -c 3 ${ip_address}    ${OS_SYSTEM_PROMPT}
479     Should Not Contain    ${output}    64 bytes
480
481 Check Metadata Access
482     [Documentation]    Try curl on the Metadataurl and check if it is okay
483     ${output}=    Write Commands Until Expected Prompt    curl -i http://169.254.169.254    ${OS_SYSTEM_PROMPT}
484     Should Contain    ${output}    200
485
486 Execute Command on VM Instance
487     [Arguments]    ${net_name}    ${vm_ip}    ${cmd}    ${user}=cirros    ${password}=cubswin:)
488     [Documentation]    Login to the vm instance using ssh in the network, executes a command inside the VM and returns the ouput.
489     Get ControlNode Connection
490     ${net_id} =    Get Net Id    ${net_name}
491     ${output} =    Write Commands Until Expected Prompt    sudo ip netns exec qdhcp-${net_id} ssh ${user}@${vm_ip} -o ConnectTimeout=10 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null    password:
492     ${output} =    Write Commands Until Expected Prompt    ${password}    ${OS_SYSTEM_PROMPT}
493     ${rcode} =    Run Keyword And Return Status    Check If Console Is VmInstance
494     ${output} =    Run Keyword If    ${rcode}    Write Commands Until Expected Prompt    ${cmd}    ${OS_SYSTEM_PROMPT}
495     [Teardown]    Exit From Vm Console
496     [Return]    ${output}
497
498 Test Operations From Vm Instance
499     [Arguments]    ${net_name}    ${src_ip}    ${dest_ips}    ${user}=cirros    ${password}=cubswin:)    ${ttl}=64
500     ...    ${ping_should_succeed}=True    ${check_metadata}=True
501     [Documentation]    Login to the vm instance using ssh in the network.
502     Get ControlNode Connection
503     ${net_id}=    Get Net Id    ${net_name}
504     ${output}=    Write Commands Until Expected Prompt    sudo ip netns exec qdhcp-${net_id} ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no ${user}@${src_ip} -o UserKnownHostsFile=/dev/null    password:
505     ${output}=    Write Commands Until Expected Prompt    ${password}    ${OS_SYSTEM_PROMPT}
506     ${rcode}=    Run Keyword And Return Status    Check If Console Is VmInstance
507     Run Keyword If    ${rcode}    Write Commands Until Expected Prompt    ifconfig    ${OS_SYSTEM_PROMPT}
508     Run Keyword If    ${rcode}    Write Commands Until Expected Prompt    route -n    ${OS_SYSTEM_PROMPT}
509     Run Keyword If    ${rcode}    Write Commands Until Expected Prompt    route -A inet6    ${OS_SYSTEM_PROMPT}
510     Run Keyword If    ${rcode}    Write Commands Until Expected Prompt    arp -an    ${OS_SYSTEM_PROMPT}
511     Run Keyword If    ${rcode}    Write Commands Until Expected Prompt    ip -f inet6 neigh show    ${OS_SYSTEM_PROMPT}
512     : FOR    ${dest_ip}    IN    @{dest_ips}
513     \    ${string_empty}=    Run Keyword And Return Status    Should Be Empty    ${dest_ip}
514     \    Run Keyword If    ${string_empty}    Continue For Loop
515     \    Run Keyword If    ${rcode} and "${ping_should_succeed}" == "True"    Check Ping    ${dest_ip}    ttl=${ttl}
516     \    ...    ELSE    Check No Ping    ${dest_ip}    ttl=${ttl}
517     ${ethertype}=    Get Regexp Matches    ${src_ip}    ${IP_REGEX}
518     Run Keyword If    ${rcode} and "${check_metadata}" and ${ethertype} == "True"    Check Metadata Access
519     [Teardown]    Exit From Vm Console
520
521 Test Netcat Operations From Vm Instance
522     [Arguments]    ${net_name}    ${vm_ip}    ${dest_ip}    ${additional_args}=${EMPTY}    ${port}=12345    ${user}=cirros
523     ...    ${password}=cubswin:)
524     [Documentation]    Use Netcat to test TCP/UDP connections to the controller
525     ${client_data}    Set Variable    Test Client Data
526     ${server_data}    Set Variable    Test Server Data
527     Get ControlNode Connection
528     ${output}=    Write Commands Until Prompt And Log    ( ( echo "${server_data}" | sudo timeout 60 nc -l ${additional_args} ${port} ) & )
529     ${output}=    Write Commands Until Prompt And Log    sudo netstat -nlap | grep ${port}
530     ${nc_output}=    Execute Command on VM Instance    ${net_name}    ${vm_ip}    sudo echo "${client_data}" | nc -v -w 5 ${additional_args} ${dest_ip} ${port}
531     ${output}=    Execute Command on VM Instance    ${net_name}    ${vm_ip}    sudo route -n
532     Log    ${output}
533     ${output}=    Execute Command on VM Instance    ${net_name}    ${vm_ip}    sudo arp -an
534     Log    ${output}
535     Should Match Regexp    ${nc_output}    ${server_data}
536
537 Ping Other Instances
538     [Arguments]    ${list_of_external_dst_ips}
539     [Documentation]    Check reachability with other network's instances.
540     ${rcode}=    Run Keyword And Return Status    Check If Console Is VmInstance
541     : FOR    ${dest_ip}    IN    @{list_of_external_dst_ips}
542     \    Check Ping    ${dest_ip}
543
544 Create Router
545     [Arguments]    ${router_name}
546     [Documentation]    Create Router and Add Interface to the subnets.
547     ${rc}    ${output}=    Run And Return Rc And Output    openstack router create ${router_name}
548     Should Be True    '${rc}' == '0'
549
550 List Routers
551     [Documentation]    List Routers and return output with neutron client.
552     ${rc}    ${output}=    Run And Return Rc And Output    openstack router list -f value
553     Log    ${output}
554     Should Be True    '${rc}' == '0'
555     [Return]    ${output}
556
557 Add Router Interface
558     [Arguments]    ${router_name}    ${interface_name}
559     ${rc}    ${output}=    Run And Return Rc And Output    openstack router add subnet ${router_name} ${interface_name}
560     Should Be True    '${rc}' == '0'
561
562 Show Router Interface
563     [Arguments]    ${router_name}
564     [Documentation]    List Routers interface associated with given Router and return output with neutron client.
565     ${rc}    ${output}=    Run And Return Rc And Output    openstack port list --router ${router_name} -f value
566     Should Be True    '${rc}' == '0'
567     [Return]    ${output}
568
569 Add Router Gateway
570     [Arguments]    ${router_name}    ${external_network_name}
571     ${cmd}=    Set Variable If    '${OPENSTACK_BRANCH}'=='stable/newton'    neutron -v router-gateway-set ${router_name} ${external_network_name}    openstack router set ${router_name} --external-gateway ${external_network_name}
572     ${rc}    ${output}=    Run And Return Rc And Output    ${cmd}
573     Should Be True    '${rc}' == '0'
574
575 Remove Interface
576     [Arguments]    ${router_name}    ${interface_name}
577     [Documentation]    Remove Interface to the subnets.
578     ${rc}    ${output}=    Run And Return Rc And Output    openstack router remove subnet ${router_name} ${interface_name}
579     Should Be True    '${rc}' == '0'
580
581 Remove Gateway
582     [Arguments]    ${router_name}
583     [Documentation]    Remove external gateway from the router.
584     BuiltIn.Log    openstack router unset ${router_name} --external-gateway
585
586 Update Router
587     [Arguments]    ${router_name}    ${cmd}
588     [Documentation]    Update the router with the command. Router name and command should be passed as argument.
589     ${rc}    ${output} =    Run And Return Rc And Output    openstack router set ${router_name} ${cmd}
590     Should Be True    '${rc}' == '0'
591
592 Show Router
593     [Arguments]    ${router_name}    ${options}
594     [Documentation]    Show information of a given router. Router name and optional fields should be sent as arguments.
595     ${rc}    ${output} =    Run And Return Rc And Output    openstack router show ${router_name}
596     Log    ${output}
597
598 Delete Router
599     [Arguments]    ${router_name}
600     [Documentation]    Delete Router and Interface to the subnets.
601     ${rc}    ${output}=    Run And Return Rc And Output    openstack router delete ${router_name}
602     Log    ${output}
603     Should Be True    '${rc}' == '0'
604
605 Get DumpFlows And Ovsconfig
606     [Arguments]    ${conn_id}
607     [Documentation]    Get the OvsConfig and Flow entries from OVS from the Openstack Node
608     SSHLibrary.Switch Connection    ${conn_id}
609     Write Commands Until Expected Prompt    ip -o link    ${DEFAULT_LINUX_PROMPT_STRICT}
610     Write Commands Until Expected Prompt    ip -o addr    ${DEFAULT_LINUX_PROMPT_STRICT}
611     Write Commands Until Expected Prompt    ip route    ${DEFAULT_LINUX_PROMPT_STRICT}
612     Write Commands Until Expected Prompt    arp -an    ${DEFAULT_LINUX_PROMPT_STRICT}
613     ${nslist}=    Write Commands Until Expected Prompt    ip netns list | awk '{print $1}'    ${DEFAULT_LINUX_PROMPT_STRICT}
614     @{lines}    Split To Lines    ${nslist}    end=-1
615     : FOR    ${line}    IN    @{lines}
616     \    Write Commands Until Expected Prompt    sudo ip netns exec ${line} ip -o link    ${DEFAULT_LINUX_PROMPT_STRICT}
617     \    Write Commands Until Expected Prompt    sudo ip netns exec ${line} ip -o addr    ${DEFAULT_LINUX_PROMPT_STRICT}
618     \    Write Commands Until Expected Prompt    sudo ip netns exec ${line} ip route    ${DEFAULT_LINUX_PROMPT_STRICT}
619     Write Commands Until Expected Prompt    sudo ovs-vsctl show    ${DEFAULT_LINUX_PROMPT_STRICT}
620     Write Commands Until Expected Prompt    sudo ovs-vsctl list Open_vSwitch    ${DEFAULT_LINUX_PROMPT_STRICT}
621     Write Commands Until Expected Prompt    sudo ovs-ofctl show br-int -OOpenFlow13    ${DEFAULT_LINUX_PROMPT_STRICT}
622     Write Commands Until Expected Prompt    sudo ovs-ofctl dump-flows br-int -OOpenFlow13    ${DEFAULT_LINUX_PROMPT_STRICT}
623     Write Commands Until Expected Prompt    sudo ovs-ofctl dump-groups br-int -OOpenFlow13    ${DEFAULT_LINUX_PROMPT_STRICT}
624     Write Commands Until Expected Prompt    sudo ovs-ofctl dump-group-stats br-int -OOpenFlow13    ${DEFAULT_LINUX_PROMPT_STRICT}
625
626 Get Karaf Log Type From Test Start
627     [Arguments]    ${ip}    ${test_name}    ${type}    ${user}=${ODL_SYSTEM_USER}    ${password}=${ODL_SYSTEM_PASSWORD}    ${prompt}=${ODL_SYSTEM_PROMPT}
628     ...    ${log_file}=${WORKSPACE}/${BUNDLEFOLDER}/data/log/karaf.log
629     ${cmd}    Set Variable    sed '1,/ROBOT MESSAGE: Starting test ${test_name}/d' ${log_file} | grep '${type}'
630     ${output}    Run Command On Controller    ${ip}    ${cmd}    ${user}    ${password}    ${prompt}
631     [Return]    ${output}
632
633 Get Karaf Log Types From Test Start
634     [Arguments]    ${ip}    ${test_name}    ${types}    ${user}=${ODL_SYSTEM_USER}    ${password}=${ODL_SYSTEM_PASSWORD}    ${prompt}=${ODL_SYSTEM_PROMPT}
635     ...    ${log_file}=${WORKSPACE}/${BUNDLEFOLDER}/data/log/karaf.log
636     : FOR    ${type}    IN    @{types}
637     \    Get Karaf Log Type From Test Start    ${ip}    ${test_name}    ${type}    ${user}    ${password}
638     \    ...    ${prompt}    ${log_file}
639
640 Get Karaf Log Events From Test Start
641     [Arguments]    ${test_name}    ${user}=${ODL_SYSTEM_USER}    ${password}=${ODL_SYSTEM_PASSWORD}    ${prompt}=${ODL_SYSTEM_PROMPT}
642     ${log_types} =    Create List    ERROR    WARN    Exception
643     Run Keyword If    0 < ${NUM_ODL_SYSTEM}    Get Karaf Log Types From Test Start    ${ODL_SYSTEM_IP}    ${test_name}    ${log_types}
644     Run Keyword If    1 < ${NUM_ODL_SYSTEM}    Get Karaf Log Types From Test Start    ${ODL_SYSTEM_2_IP}    ${test_name}    ${log_types}
645     Run Keyword If    2 < ${NUM_ODL_SYSTEM}    Get Karaf Log Types From Test Start    ${ODL_SYSTEM_3_IP}    ${test_name}    ${log_types}
646
647 Get ControlNode Connection
648     SSHLibrary.Switch Connection    ${OS_CNTL_CONN_ID}
649     [Return]    ${OS_CNTL_CONN_ID}
650
651 Get OvsDebugInfo
652     [Documentation]    Get the OvsConfig and Flow entries from all Openstack nodes
653     Run Keyword If    0 < ${NUM_OS_SYSTEM}    Get DumpFlows And Ovsconfig    ${OS_CNTL_CONN_ID}
654     Run Keyword If    1 < ${NUM_OS_SYSTEM}    Get DumpFlows And Ovsconfig    ${OS_CMP1_CONN_ID}
655     Run Keyword If    2 < ${NUM_OS_SYSTEM}    Get DumpFlows And Ovsconfig    ${OS_CMP2_CONN_ID}
656
657 Get Test Teardown Debugs
658     [Arguments]    ${test_name}=${TEST_NAME}
659     Get OvsDebugInfo
660     Run Keyword And Ignore Error    Get Model Dump    ${HA_PROXY_IP}    ${netvirt_data_models}
661     Get Karaf Log Events From Test Start    ${test_name}
662
663 Get Test Teardown Debugs For SFC
664     [Arguments]    ${test_name}=${TEST_NAME}
665     Run Keyword And Ignore Error    Get Model Dump    ${HA_PROXY_IP}    ${netvirt_sfc_data_models}
666
667 Show Debugs
668     [Arguments]    @{vm_indices}
669     [Documentation]    Run these commands for debugging, it can list state of VM instances and ip information in control node
670     Get ControlNode Connection
671     ${output}=    Write Commands Until Prompt And Log    sudo ip netns list
672     : FOR    ${index}    IN    @{vm_indices}
673     \    ${rc}    ${output}=    Run And Return Rc And Output    nova show ${index}
674     \    Log    ${output}
675     List Nova VMs
676     List Routers
677     List Networks
678     List Subnets
679     List Ports
680     List Security Groups
681
682 List Security Groups
683     [Documentation]    Logging keyword to display all security groups using the openstack cli. Assumes openstack
684     ...    credentials are already sourced
685     ${rc}    ${output}=    Run And Return Rc And Output    openstack security group list
686     Log    ${output}
687     Should Be True    '${rc}' == '0'
688     [Return]    ${output}
689
690 Neutron Security Group Show
691     [Arguments]    ${SecurityGroupRuleName}
692     [Documentation]    Displays the neutron security group configurations that belongs to a given neutron security group name
693     ${rc}    ${output}=    Run And Return Rc And Output    openstack security group show ${SecurityGroupRuleName}
694     Log    ${output}
695     Should Be True    '${rc}' == '0'
696     [Return]    ${output}
697
698 Neutron Port Show
699     [Arguments]    ${PortName}
700     [Documentation]    Display the port configuration that belong to a given neutron port
701     ${rc}    ${output}=    Run And Return Rc And Output    openstack port show ${PortName}
702     Log    ${output}
703     Should Be True    '${rc}' == '0'
704     [Return]    ${output}
705
706 Neutron Security Group Create
707     [Arguments]    ${SecurityGroupName}    ${additional_args}=${EMPTY}
708     [Documentation]    Create a security group with specified name ,description & protocol value according to security group template
709     Get ControlNode Connection
710     ${rc}    ${output}=    Run And Return Rc And Output    openstack security group create ${SecurityGroupName} ${additional_args}
711     Log    ${output}
712     Should Be True    '${rc}' == '0'
713     ${sgp_id}=    Should Match Regexp    ${output}    [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
714     Log    ${sgp_id}
715     [Return]    ${output}    ${sgp_id}
716
717 Neutron Security Group Update
718     [Arguments]    ${SecurityGroupName}    ${additional_args}=${EMPTY}
719     [Documentation]    Updating security groups
720     ${rc}    ${output}=    Run And Return Rc And Output    openstack security group set ${SecurityGroupName} ${additional_args}
721     Log    ${output}
722     Should Be True    '${rc}' == '0'
723     [Return]    ${output}
724
725 Delete SecurityGroup
726     [Arguments]    ${sg_name}
727     [Documentation]    Delete Security group
728     ${rc}    ${output}=    Run And Return Rc And Output    openstack security group delete ${sg_name}
729     Log    ${output}
730     Should Be True    '${rc}' == '0'
731
732 Neutron Security Group Rule Create
733     [Arguments]    ${Security_group_name}    &{Kwargs}
734     [Documentation]    Creates neutron security rule with Openstack CLI with or without optional params, here security group name is mandatory args, rule with optional params can be created by passing the optional args values ex: direction=${INGRESS_EGRESS}, Then these optional params are catenated with mandatory args, example of usage: "Neutron Security Group Rule Create ${SGP_SSH} direction=${RULE_PARAMS[0]} ethertype=${RULE_PARAMS[1]} ..."
735     Run Keyword If    ${Kwargs}    Log    ${Kwargs}
736     ${description}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    description    default=${None}
737     ${direction}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    direction    default=${None}
738     ${ethertype}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    ethertype    default=${None}
739     ${port_range_max}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    port_range_max    default=${None}
740     ${port_range_min}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    port_range_min    default=${None}
741     ${protocol}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    protocol    default=${None}
742     ${remote_group_id}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    remote_group_id    default=${None}
743     ${remote_ip_prefix}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    remote_ip_prefix    default=${None}
744     ${cmd}=    Set Variable    openstack security group rule create ${Security_group_name}
745     ${cmd}=    Run Keyword If    '${description}'!='None'    Catenate    ${cmd}    --description ${description}
746     ...    ELSE    Catenate    ${cmd}
747     ${cmd}=    Run Keyword If    '${direction}'!='None'    Catenate    ${cmd}    --${direction}
748     ...    ELSE    Catenate    ${cmd}
749     ${cmd}=    Run Keyword If    '${ethertype}'!='None'    Catenate    ${cmd}    --ethertype ${ethertype}
750     ...    ELSE    Catenate    ${cmd}
751     ${cmd}=    Run Keyword If    '${port_range_min}'!='None' and '${port_range_max}'!='None'    Catenate    ${cmd}    --dst-port ${port_range_min}:${port_range_max}
752     ...    ELSE IF    '${port_range_max}'!='None'    Catenate    ${cmd}    --dst-port ${port_range_max}
753     ...    ELSE IF    '${port_range_min}'!='None'    Catenate    ${cmd}    --dst-port ${port_range_min}
754     ...    ELSE    Catenate    ${cmd}
755     ${cmd}=    Run Keyword If    '${protocol}'!='None'    Catenate    ${cmd}    --protocol ${protocol}
756     ...    ELSE    Catenate    ${cmd}
757     ${cmd}=    Run Keyword If    '${remote_group_id}'!='None'    Catenate    ${cmd}    --remote-group ${remote_group_id}
758     ...    ELSE    Catenate    ${cmd}
759     ${cmd}=    Run Keyword If    '${remote_ip_prefix}'!='None'    Catenate    ${cmd}    --src-ip ${remote_ip_prefix}
760     ...    ELSE    Catenate    ${cmd}
761     ${rc}    ${output}=    Run And Return Rc And Output    ${cmd}
762     ${rule_id}=    Should Match Regexp    ${output}    [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
763     Log    ${rule_id}
764     Should Be True    '${rc}' == '0'
765     [Return]    ${output}    ${rule_id}
766
767 Neutron Security Group Rule Create Legacy Cli
768     [Arguments]    ${Security_group_name}    &{Kwargs}
769     [Documentation]    Creates neutron security rule with neutron request with or without optional params, here security group name is mandatory args, rule with optional params can be created by passing the optional args values ex: direction=${INGRESS_EGRESS}, Then these optional params are catenated with mandatory args, example of usage: "Neutron Security Group Rule Create ${SGP_SSH} direction=${RULE_PARAMS[0]} ethertype=${RULE_PARAMS[1]} ..."
770     Run Keyword If    ${Kwargs}    Log    ${Kwargs}
771     ${description}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    description    default=${None}
772     ${direction}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    direction    default=${None}
773     ${ethertype}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    ethertype    default=${None}
774     ${port_range_max}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    port_range_max    default=${None}
775     ${port_range_min}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    port_range_min    default=${None}
776     ${protocol}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    protocol    default=${None}
777     ${remote_group_id}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    remote_group_id    default=${None}
778     ${remote_ip_prefix}    Run Keyword If    ${Kwargs}    Pop From Dictionary    ${Kwargs}    remote_ip_prefix    default=${None}
779     ${cmd}=    Set Variable    neutron security-group-rule-create ${Security_group_name}
780     ${cmd}=    Run Keyword If    '${description}'!='None'    Catenate    ${cmd}    --description ${description}
781     ...    ELSE    Catenate    ${cmd}
782     ${cmd}=    Run Keyword If    '${direction}'!='None'    Catenate    ${cmd}    --direction ${direction}
783     ...    ELSE    Catenate    ${cmd}
784     ${cmd}=    Run Keyword If    '${ethertype}'!='None'    Catenate    ${cmd}    --ethertype ${ethertype}
785     ...    ELSE    Catenate    ${cmd}
786     ${cmd}=    Run Keyword If    '${port_range_max}'!='None'    Catenate    ${cmd}    --port_range_max ${port_range_max}
787     ...    ELSE    Catenate    ${cmd}
788     ${cmd}=    Run Keyword If    '${port_range_min}'!='None'    Catenate    ${cmd}    --port_range_min ${port_range_min}
789     ...    ELSE    Catenate    ${cmd}
790     ${cmd}=    Run Keyword If    '${protocol}'!='None'    Catenate    ${cmd}    --protocol ${protocol}
791     ...    ELSE    Catenate    ${cmd}
792     ${cmd}=    Run Keyword If    '${remote_group_id}'!='None'    Catenate    ${cmd}    --remote_group_id ${remote_group_id}
793     ...    ELSE    Catenate    ${cmd}
794     ${cmd}=    Run Keyword If    '${remote_ip_prefix}'!='None'    Catenate    ${cmd}    --remote_ip_prefix ${remote_ip_prefix}
795     ...    ELSE    Catenate    ${cmd}
796     ${rc}    ${output}=    Run And Return Rc And Output    ${cmd}
797     ${rule_id}=    Should Match Regexp    ${output}    [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
798     Log    ${rule_id}
799     Should Be True    '${rc}' == '0'
800     [Return]    ${output}    ${rule_id}
801
802 Security Group Create Without Default Security Rules
803     [Arguments]    ${sg_name}    ${additional_args}=${EMPTY}
804     [Documentation]    Create Neutron Security Group with no default rules, using specified name and optional arguments.
805     Neutron Security Group Create    ${sg_name}    ${additional_args}
806     Delete All Security Group Rules    ${sg_name}
807
808 Delete All Security Group Rules
809     [Arguments]    ${sg_name}
810     [Documentation]    Delete all security rules from a specified security group
811     ${rc}    ${sg_rules_output}=    Run And Return Rc And Output    openstack security group rule list ${sg_name} -cID -fvalue
812     Log    ${sg_rules_output}
813     Should Be True    '${rc}' == '0'
814     @{sg_rules}=    Split String    ${sg_rules_output}    \n
815     : FOR    ${rule}    IN    @{sg_rules}
816     \    ${rc}    ${output}=    Run And Return Rc And Output    openstack security group rule delete ${rule}
817     \    Log    ${output}
818     \    Should Be True    '${rc}' == '0'
819
820 Create Allow All SecurityGroup
821     [Arguments]    ${sg_name}    ${ether_type}=IPv4
822     [Documentation]    Allow all TCP/UDP/ICMP packets for this suite
823     Neutron Security Group Create    ${sg_name}
824     Neutron Security Group Rule Create    ${sg_name}    direction=ingress    ethertype=${ether_type}    port_range_max=65535    port_range_min=1    protocol=tcp
825     Neutron Security Group Rule Create    ${sg_name}    direction=egress    ethertype=${ether_type}    port_range_max=65535    port_range_min=1    protocol=tcp
826     Neutron Security Group Rule Create    ${sg_name}    direction=ingress    ethertype=${ether_type}    protocol=icmp
827     Neutron Security Group Rule Create    ${sg_name}    direction=egress    ethertype=${ether_type}    protocol=icmp
828     Neutron Security Group Rule Create    ${sg_name}    direction=ingress    ethertype=${ether_type}    port_range_max=65535    port_range_min=1    protocol=udp
829     Neutron Security Group Rule Create    ${sg_name}    direction=egress    ethertype=${ether_type}    port_range_max=65535    port_range_min=1    protocol=udp
830
831 Create Neutron Port With Additional Params
832     [Arguments]    ${network_name}    ${port_name}    ${additional_args}=${EMPTY}
833     [Documentation]    Create Port With given additional parameters
834     ${rc}    ${output}=    Run And Return Rc And Output    neutron -v port-create ${network_name} --name ${port_name} ${additional_args}
835     Log    ${output}
836     Should Be True    '${rc}' == '0'
837     ${port_id}=    Should Match Regexp    ${OUTPUT}    [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
838     Log    ${port_id}
839     [Return]    ${OUTPUT}    ${port_id}
840
841 Get Ports MacAddr
842     [Arguments]    ${portName_list}
843     [Documentation]    Retrieve the port MacAddr for the given list of port name and return the MAC address list.
844     ${MacAddr-list}    Create List
845     : FOR    ${portName}    IN    @{portName_list}
846     \    ${macAddr}=    OpenStackOperations.Get Port Mac    ${portName}
847     \    Append To List    ${MacAddr-list}    ${macAddr}
848     [Return]    ${MacAddr-list}
849
850 Get Port Ip
851     [Arguments]    ${port_name}
852     [Documentation]    Keyword would return the IP of the ${port_name} received.
853     ${rc}    ${output}=    Run And Return Rc And Output    openstack port list | grep "${port_name}" | awk -F\\' '{print $2}'
854     ${splitted_output}=    Split String    ${output}    ${EMPTY}
855     ${port_ip}=    Get from List    ${splitted_output}    0
856     Should Be True    '${rc}' == '0'
857     [Return]    ${port_ip}
858
859 Get Port Mac
860     [Arguments]    ${port_name}
861     [Documentation]    Keyword would return the MAC ID of the ${port_name} received.
862     ${rc}    ${output}=    Run And Return Rc And Output    openstack port show ${port_name} | grep mac_address | awk '{print $4}'
863     ${splitted_output}=    Split String    ${output}    ${EMPTY}
864     ${port_mac}=    Get from List    ${splitted_output}    0
865     Should Be True    '${rc}' == '0'
866     [Return]    ${port_mac}
867
868 Create L2Gateway
869     [Arguments]    ${bridge_name}    ${intf_name}    ${gw_name}
870     [Documentation]    Keyword to create an L2 Gateway ${gw_name} for bridge ${bridge_name} connected to interface ${intf_name} (Using Neutron CLI).
871     ${rc}    ${l2gw_output}=    Run And Return Rc And Output    ${L2GW_CREATE} name=${bridge_name},interface_names=${intf_name} ${gw_name}
872     Log    ${l2gw_output}
873     [Return]    ${l2gw_output}
874
875 Create L2Gateway Connection
876     [Arguments]    ${gw_name}    ${net_name}
877     [Documentation]    Keyword would create a new L2 Gateway Connection for ${gw_name} to ${net_name} (Using Neutron CLI).
878     ${rc}    ${l2gw_output}=    Run And Return Rc And Output    ${L2GW_CONN_CREATE} ${gw_name} ${net_name}
879     Log    ${l2gw_output}
880     Should Be True    '${rc}' == '0'
881     [Return]    ${l2gw_output}
882
883 Get All L2Gateway
884     [Documentation]    Keyword to return all the L2 Gateways available (Using Neutron CLI).
885     ${rc}    ${output}=    Run And Return Rc And Output    ${L2GW_GET_YAML}
886     Should Be True    '${rc}' == '0'
887     [Return]    ${output}
888
889 Get All L2Gateway Connection
890     [Documentation]    Keyword to return all the L2 Gateway connections available (Using Neutron CLI).
891     ${rc}    ${output}=    Run And Return Rc And Output    ${L2GW_GET_CONN_YAML}
892     Should Be True    '${rc}' == '0'
893     [Return]    ${output}
894
895 Get L2Gateway
896     [Arguments]    ${gw_id}
897     [Documentation]    Keyword to check if the ${gw_id} is available in the L2 Gateway list (Using Neutron CLI).
898     ${rc}    ${output}=    Run And Return Rc And Output    ${L2GW_SHOW} ${gw_id}
899     Log    ${output}
900     Should Be True    '${rc}' == '0'
901     [Return]    ${output}
902
903 Get L2gw Id
904     [Arguments]    ${l2gw_name}
905     [Documentation]    Keyword to retrieve the L2 Gateway ID for the ${l2gw_name} (Using Neutron CLI).
906     ${rc}    ${output}=    Run And Return Rc And Output    ${L2GW_GET} | grep "${l2gw_name}" | awk '{print $2}'
907     Log    ${output}
908     Should Be True    '${rc}' == '0'
909     ${splitted_output}=    Split String    ${output}    ${EMPTY}
910     ${l2gw_id}=    Get from List    ${splitted_output}    0
911     [Return]    ${l2gw_id}
912
913 Get L2gw Connection Id
914     [Arguments]    ${l2gw_name}
915     [Documentation]    Keyword to retrieve the L2 Gateway Connection ID for the ${l2gw_name} (Using Neutron CLI).
916     ${l2gw_id}=    OpenStackOperations.Get L2gw Id    ${l2gw_name}
917     ${rc}    ${output}=    Run And Return Rc And Output    ${L2GW_GET_CONN} | grep "${l2gw_id}" | awk '{print $2}'
918     Should Be True    '${rc}' == '0'
919     ${splitted_output}=    Split String    ${output}    ${EMPTY}
920     ${splitted_output}=    Split String    ${output}    ${EMPTY}
921     ${l2gw_conn_id}=    Get from List    ${splitted_output}    0
922     [Return]    ${l2gw_conn_id}
923
924 Neutron Port List Rest
925     [Documentation]    Keyword to get all ports details in Neutron (Using REST).
926     ${resp} =    RequestsLibrary.Get Request    session    ${PORT_URL}
927     Log    ${resp.content}
928     Should Be Equal As Strings    ${resp.status_code}    200
929     [Return]    ${resp.content}
930
931 Get Neutron Port Rest
932     [Arguments]    ${port_id}
933     [Documentation]    Keyword to get the specific port details in Neutron (Using REST).
934     ${resp} =    RequestsLibrary.Get Request    session    ${CONFIG_API}/${GET_PORT_URL}/${port_id}
935     Log    ${resp.content}
936     Should Be Equal As Strings    ${resp.status_code}    200
937     [Return]    ${resp.content}
938
939 Update Port Rest
940     [Arguments]    ${port_id}    ${json_data}
941     [Documentation]    Keyword to update ${port_id} with json data received in ${json_data} (Using REST).
942     Log    ${json_data}
943     ${resp} =    RequestsLibrary.Put Request    session    ${CONFIG_API}/${GET_PORT_URL}/${port_id}    ${json_data}
944     Log    ${resp.content}
945     Should Be Equal As Strings    ${resp.status_code}    200
946     [Return]    ${resp.content}
947
948 Create And Configure Security Group
949     [Arguments]    ${sg-name}
950     [Documentation]    Create Security Group with given name, and default allow rules for TCP/UDP/ICMP protocols.
951     Neutron Security Group Create    ${sg-name}
952     Neutron Security Group Rule Create    ${sg-name}    direction=ingress    port_range_max=65535    port_range_min=1    protocol=tcp    remote_ip_prefix=0.0.0.0/0
953     Neutron Security Group Rule Create    ${sg-name}    direction=egress    port_range_max=65535    port_range_min=1    protocol=tcp    remote_ip_prefix=0.0.0.0/0
954     Neutron Security Group Rule Create    ${sg-name}    direction=ingress    protocol=icmp    remote_ip_prefix=0.0.0.0/0
955     Neutron Security Group Rule Create    ${sg-name}    direction=egress    protocol=icmp    remote_ip_prefix=0.0.0.0/0
956     Neutron Security Group Rule Create    ${sg-name}    direction=ingress    port_range_max=65535    port_range_min=1    protocol=udp    remote_ip_prefix=0.0.0.0/0
957     Neutron Security Group Rule Create    ${sg-name}    direction=egress    port_range_max=65535    port_range_min=1    protocol=udp    remote_ip_prefix=0.0.0.0/0
958
959 Add Security Group To VM
960     [Arguments]    ${vm}    ${sg}
961     [Documentation]    Add the security group provided to the given VM.
962     ${rc}    ${output}=    Run And Return Rc And Output    openstack server add security group ${vm} ${sg}
963     Log    ${output}
964     Should Be True    '${rc}' == '0'
965
966 Remove Security Group From VM
967     [Arguments]    ${vm}    ${sg}
968     [Documentation]    Remove the security group provided to the given VM.
969     Get ControlNode Connection
970     ${output}=    Write Commands Until Prompt And Log    openstack server remove security group ${vm} ${sg}
971
972 Create SFC Flow Classifier
973     [Arguments]    ${name}    ${src_ip}    ${dest_ip}    ${protocol}    ${dest_port}    ${neutron_src_port}
974     [Documentation]    Create a flow classifier for SFC
975     ${rc}    ${output}=    Run And Return Rc And Output    openstack sfc flow classifier create --ethertype IPv4 --source-ip-prefix ${src_ip}/32 --destination-ip-prefix ${dest_ip}/32 --protocol ${protocol} --destination-port ${dest_port}:${dest_port} --logical-source-port ${neutron_src_port} ${name}
976     Log    ${output}
977     Should Be True    '${rc}' == '0'
978     Should Contain    ${output}    ${name}
979     [Return]    ${output}
980
981 Delete SFC Flow Classifier
982     [Arguments]    ${name}
983     [Documentation]    Delete a SFC flow classifier
984     Get ControlNode Connection
985     ${rc}    ${output}=    Run And Return Rc And Output    openstack sfc flow classifier delete ${name}
986     Log    ${output}
987     Should Be True    '${rc}' == '0'
988     [Return]    ${output}
989
990 Create SFC Port Pair
991     [Arguments]    ${name}    ${port_in}    ${port_out}
992     [Documentation]    Creates a neutron port pair for SFC
993     Get ControlNode Connection
994     ${rc}    ${output}=    Run And Return Rc And Output    openstack sfc port pair create --ingress=${port_in} --egress=${port_out} ${name}
995     Log    ${output}
996     Should Be True    '${rc}' == '0'
997     Should Contain    ${output}    ${name}
998     [Return]    ${output}
999
1000 Delete SFC Port Pair
1001     [Arguments]    ${name}
1002     [Documentation]    Delete a SFC port pair
1003     ${rc}    ${output}=    Run And Return Rc And Output    openstack sfc port pair delete ${name}
1004     Log    ${output}
1005     Should Be True    '${rc}' == '0'
1006     [Return]    ${output}
1007
1008 Create SFC Port Pair Group
1009     [Arguments]    ${name}    ${port_pair}
1010     [Documentation]    Creates a port pair group with a single port pair for SFC
1011     ${rc}    ${output}=    Run And Return Rc And Output    openstack sfc port pair group create --port-pair ${port_pair} ${name}
1012     Log    ${output}
1013     Should Be True    '${rc}' == '0'
1014     Should Contain    ${output}    ${name}
1015     [Return]    ${output}
1016
1017 Create SFC Port Pair Group With Two Pairs
1018     [Arguments]    ${name}    ${port_pair1}    ${port_pair2}
1019     [Documentation]    Creates a port pair group with two port pairs for SFC
1020     ${rc}    ${output}=    Run And Return Rc And Output    openstack sfc port pair group create --port-pair ${port_pair1} --port-pair ${port_pair2} ${name}
1021     Log    ${output}
1022     Should Be True    '${rc}' == '0'
1023     Should Contain    ${output}    ${name}
1024     [Return]    ${output}
1025
1026 Delete SFC Port Pair Group
1027     [Arguments]    ${name}
1028     [Documentation]    Delete a SFC port pair group
1029     Get ControlNode Connection
1030     ${rc}    ${output}=    Run And Return Rc And Output    openstack sfc port pair group delete ${name}
1031     Log    ${output}
1032     Should Be True    '${rc}' == '0'
1033     [Return]    ${output}
1034
1035 Create SFC Port Chain
1036     [Arguments]    ${name}    ${pg1}    ${pg2}    ${fc}
1037     [Documentation]    Creates a port pair chain with two port groups and a singel classifier.
1038     ${rc}    ${output}=    Run And Return Rc And Output    openstack sfc port chain create --port-pair-group ${pg1} --port-pair-group ${pg2} --flow-classifier ${fc} ${name}
1039     Log    ${output}
1040     Should Be True    '${rc}' == '0'
1041     Should Contain    ${output}    ${name}
1042     [Return]    ${output}
1043
1044 Delete SFC Port Chain
1045     [Arguments]    ${name}
1046     [Documentation]    Delete a SFC port chain
1047     ${rc}    ${output}=    Run And Return Rc And Output    openstack sfc port chain delete ${name}
1048     Log    ${output}
1049     Should Be True    '${rc}' == '0'
1050     [Return]    ${output}
1051
1052 Reboot Nova VM
1053     [Arguments]    ${vm_name}
1054     [Documentation]    Reboot NOVA VM
1055     ${rc}    ${output}=    Run And Return Rc And Output    openstack server reboot --wait ${vm_name}
1056     Log    ${output}
1057     Should Be True    '${rc}' == '0'
1058     Wait Until Keyword Succeeds    35s    10s    Verify VM Is ACTIVE    ${vm_name}
1059
1060 Remove RSA Key From KnownHosts
1061     [Arguments]    ${vm_ip}
1062     [Documentation]    Remove RSA
1063     Get ControlNode Connection
1064     ${output}=    Write Commands Until Prompt And Log    sudo cat /root/.ssh/known_hosts    30s
1065     ${output}=    Write Commands Until Prompt And Log    sudo ssh-keygen -f "/root/.ssh/known_hosts" -R ${vm_ip}    30s
1066     ${output}=    Write Commands Until Prompt    sudo cat "/root/.ssh/known_hosts"    30s
1067
1068 Wait For Routes To Propogate
1069     [Arguments]    ${networks}    ${subnets}
1070     [Documentation]    Check propagated routes
1071     Get ControlNode Connection
1072     : FOR    ${INDEX}    IN RANGE    0    1
1073     \    ${net_id}=    Get Net Id    @{networks}[${INDEX}]
1074     \    ${is_ipv6}=    Get Regexp Matches    @{subnets}[${INDEX}]    ${IP6_REGEX}
1075     \    ${length}=    Get Length    ${is_ipv6}
1076     \    ${cmd}=    Set Variable If    ${length} == 0    ip route    ip -6 route
1077     \    ${output}=    Write Commands Until Expected Prompt    sudo ip netns exec qdhcp-${net_id} ${cmd}    ]>
1078     \    Should Contain    ${output}    @{subnets}[${INDEX}]
1079
1080 Neutron Cleanup
1081     [Arguments]    ${vms}=@{EMPTY}    ${networks}=@{EMPTY}    ${subnets}=@{EMPTY}    ${ports}=@{EMPTY}    ${sgs}=@{EMPTY}
1082     : FOR    ${vm}    IN    @{vms}
1083     \    BuiltIn.Run Keyword And Ignore Error    Delete Vm Instance    ${vm}
1084     : FOR    ${port}    IN    @{ports}
1085     \    BuiltIn.Run Keyword And Ignore Error    Delete Port    ${port}
1086     : FOR    ${subnet}    IN    @{subnets}
1087     \    BuiltIn.Run Keyword And Ignore Error    Delete SubNet    ${subnet}
1088     : FOR    ${network}    IN    @{networks}
1089     \    BuiltIn.Run Keyword And Ignore Error    Delete Network    ${network}
1090     : FOR    ${sg}    IN    @{sgs}
1091     \    BuiltIn.Run Keyword And Ignore Error    Delete SecurityGroup    ${sg}
1092
1093 OpenStack List All
1094     [Documentation]    Get a list of different OpenStack resources that might be in use.
1095     @{modules} =    BuiltIn.Create List    floating ip    server    router    port    network
1096     ...    subnet    security group    security group rule
1097     : FOR    ${module}    IN    @{modules}
1098     \    OpenStack CLI    openstack ${module} list
1099
1100 OpenStack CLI Get List
1101     [Arguments]    ${cmd}
1102     [Documentation]    Return a json list from the output of an OpenStack command.
1103     ${json} =    OpenStack CLI    ${cmd}
1104     @{list} =    RequestsLibrary.To Json    ${json}
1105     BuiltIn.Log    ${list}
1106     [Return]    @{list}
1107
1108 OpenStack CLI
1109     [Arguments]    ${cmd}
1110     [Documentation]    Run the given OpenStack ${cmd}.
1111     ${rc}    ${output} =    OperatingSystem.Run And Return Rc And Output    ${cmd}
1112     BuiltIn.Log    ${output}
1113     Should Be True    '${rc}' == '0'
1114     [Return]    ${output}
1115
1116 OpenStack Cleanup All
1117     [Documentation]    Cleanup all Openstack resources with best effort. The keyword will query for all resources
1118     ...    in use and then attempt to delete them. Errors are ignored to allow the cleanup to continue.
1119     @{fips} =    OpenStack CLI Get List    openstack floating ip list -f json
1120     : FOR    ${fip}    IN    @{fips}
1121     \    BuiltIn.Run Keyword And Ignore Error    Delete Floating IP    ${fip['ID']}
1122     @{vms} =    OpenStack CLI Get List    openstack server list -f json
1123     : FOR    ${vm}    IN    @{vms}
1124     \    BuiltIn.Run Keyword And Ignore Error    Delete Vm Instance    ${vm['ID']}
1125     @{routers} =    OpenStack CLI Get List    openstack router list -f json
1126     : FOR    ${router}    IN    @{routers}
1127     \    BuiltIn.Run Keyword And Ignore Error    Cleanup Router    ${router['ID']}
1128     @{ports} =    OpenStack CLI Get List    openstack port list -f json
1129     : FOR    ${port}    IN    @{ports}
1130     \    BuiltIn.Run Keyword And Ignore Error    Delete Port    ${port['ID']}
1131     @{networks} =    OpenStack CLI Get List    openstack network list -f json
1132     : FOR    ${network}    IN    @{networks}
1133     \    BuiltIn.Run Keyword And Ignore Error    Delete Subnet    ${network['Subnets']}
1134     \    BuiltIn.Run Keyword And Ignore Error    Delete Network    ${network['ID']}
1135     @{security_groups} =    OpenStack CLI Get List    openstack security group list -f json
1136     : FOR    ${security_group}    IN    @{security_groups}
1137     \    BuiltIn.Run Keyword If    "${security_group['Name']}" != "default"    BuiltIn.Run Keyword And Ignore Error    Delete SecurityGroup    ${security_group['ID']}
1138     OpenStack List All
1139
1140 Cleanup Router
1141     [Arguments]    ${id}
1142     [Documentation]    Delete a router, but first remove any interfaces or gateways so that the delete will be successful.
1143     @{ports} =    OpenStack CLI Get List    openstack port list --router ${id} -f json --long
1144     : FOR    ${port}    IN    @{ports}
1145     \    ${subnet_id} =    Get Match    ${port['Fixed IP Addresses']}    [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}    0
1146     \    BuiltIn.Run Keyword If    "${port['Device Owner']}" == "network:router_gateway"    BuiltIn.Run Keyword And Ignore Error    Remove Gateway    ${id}
1147     \    BuiltIn.Run Keyword If    "${port['Device Owner']}" == "network:router_interface"    BuiltIn.Run Keyword And Ignore Error    Remove Interface    ${id}    ${subnet_id}
1148     BuiltIn.Run Keyword And Ignore Error    Delete Router    ${id}
1149
1150 OpenStack Suite Setup
1151     [Documentation]    Wrapper teardown keyword that can be used in any suite running in an openstack environement
1152     SetupUtils.Setup_Utils_For_Setup_And_Teardown
1153     DevstackUtils.Devstack Suite Setup
1154
1155 OpenStack Suite Teardown
1156     [Documentation]    Wrapper teardown keyword that can be used in any suite running in an openstack environement
1157     ...    to clean up all openstack resources. For example, all instances, networks, ports, etc will be listed and
1158     ...    and deleted. As other global cleanup tasks are needed, they can be added here and the suites will all
1159     ...    benefit automatically.
1160     OpenStack Cleanup All
1161     SSHLibrary.Close All Connections
1162
1163 Copy DHCP Files From Control Node
1164     [Documentation]    Copy the current DHCP files to the robot vm. The keyword must be called
1165     ...    after the subnet(s) are created and before the subnet(s) are deleted.
1166     ${suite_} =    BuiltIn.Evaluate    """${SUITE_NAME}""".replace(" ","_").replace("/","_").replace(".","_")
1167     ${dstdir} =    Set Variable    /tmp/qdhcp/${suite_}
1168     OperatingSystem.Create Directory    ${dstdir}
1169     Get ControlNode Connection
1170     BuiltIn.Run Keyword And Ignore Error    SSHLibrary.Get Directory    /opt/stack/data/neutron/dhcp    ${dstdir}    recursive=True
1171
1172 Is Feature Installed
1173     [Arguments]    ${features}=none
1174     : FOR    ${feature}    IN    ${features}
1175     \    ${status}    ${output}    Run Keyword And Ignore Error    Builtin.Should Contain    ${CONTROLLERFEATURES}    ${feature}
1176     \    Return From Keyword If    "${status}" == "PASS"    True
1177     [Return]    False