fix(core): Docker detection
[csit.git] / resources / libraries / robot / shared / container.robot
1 # Copyright (c) 2023 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 *** Settings ***
15 | Documentation | Keywords related to linux containers
16 |
17 | Library | resources.libraries.python.CpuUtils
18 | Library | resources.libraries.python.topology.Topology
19 | Variables | resources/libraries/python/Constants.py
20
21 *** Keywords ***
22 | Construct container on all DUTs
23 | | [Documentation] | Construct 1 CNF of specific technology on all DUT nodes.
24 | |
25 | | ... | *Arguments:*
26 | | ... | - nf_chains: Total number of chains (Optional). Type: integer, default
27 | | ... | value: ${1}
28 | | ... | - nf_nodes: Total number of nodes per chain (Optional). Type: integer,
29 | | ... | default value: ${1}
30 | | ... | - nf_chain: Chain ID (Optional). Type: integer, default value: ${1}
31 | | ... | - nf_node: Node ID (Optional). Type: integer, default value: ${1}
32 | | ... | - auto_scale - If True, use same amount of Dataplane threads for
33 | | ... | network function as DUT, otherwise use single physical core for
34 | | ... | every network function. Type: boolean
35 | | ... | - pinning: Set True if CPU pinning should be done on starting
36 | | ... | containers. Type: boolean, default value: ${False}
37 | |
38 | | ... | *Example:*
39 | |
40 | | ... | \| Construct container on all DUTs \| 1 \| 1 \| 1 \| 1 \| ${True} \|
41 | |
42 | | [Arguments] | ${nf_chains}=${1} | ${nf_nodes}=${1} | ${nf_chain}=${1}
43 | | ... | ${nf_node}=${1} | ${auto_scale}=${True} | ${pinning}=${True}
44 | |
45 | | ${duts}= | Get Matches | ${nodes} | DUT*
46 | | FOR | ${dut} | IN | @{duts}
47 | | | Run Keyword | Construct container on DUT | ${dut}
48 | | | ... | ${nf_chains} | ${nf_nodes} | ${nf_chain}
49 | | | ... | ${nf_node} | ${auto_scale} | ${pinning}
50 | | END
51
52 | Construct container on DUT
53 | | [Documentation] | Construct 1 CNF of specific technology on specific DUT.
54 | |
55 | | ... | *Arguments:*
56 | | ... | - dut: DUT node to construct the CNF on. Type: string
57 | | ... | - nf_chains: Total number of chains (Optional). Type: integer, default
58 | | ... | value: ${1}
59 | | ... | - nf_nodes: Total number of nodes per chain (Optional). Type: integer,
60 | | ... | default value: ${1}
61 | | ... | - nf_chain: Chain ID (Optional). Type: integer, default value: ${1}
62 | | ... | - nf_node: Node ID (Optional). Type: integer, default value: ${1}
63 | | ... | - auto_scale - If True, use same amount of Dataplane threads for
64 | | ... | network function as DUT, otherwise use single physical core for
65 | | ... | every network function. Type: boolean
66 | | ... | - pinning: Set True if CPU pinning should be done on starting
67 | | ... | containers. Type: boolean, default value: ${False}
68 | |
69 | | ... | *Example:*
70 | |
71 | | ... | \| Construct container on DUT \| DUT1 \| 1 \| 1 \| 1 \| 1 \|
72 | | ... | \| ${True} \|
73 | |
74 | | [Arguments] | ${dut}
75 | | ... | ${nf_chains}=${1} | ${nf_nodes}=${1} | ${nf_chain}=${1}
76 | | ... | ${nf_node}=${1} | ${auto_scale}=${True} | ${pinning}=${True}
77 | |
78 | | ${nf_dtcr_status} | ${value}= | Run Keyword And Ignore Error
79 | | ... | Variable Should Exist | ${nf_dtcr}
80 | | ${nf_dtcr}= | Run Keyword If | '${nf_dtcr_status}' == 'PASS'
81 | | ... | Set Variable | ${nf_dtcr} | ELSE | Set Variable | ${1}
82 | | ${nf_dtc}= | Run Keyword If | ${pinning}
83 | | ... | Set Variable If | ${auto_scale} | ${cpu_count_int}
84 | | ... | ${nf_dtc}
85 | | ${nf_id}= | Evaluate | (${nf_chain} - ${1}) * ${nf_nodes} + ${nf_node}
86 | | ${env}= | Create List | DEBIAN_FRONTEND=noninteractive
87 | | ${dut1_uuid_length} = | Get Length | ${DUT1_UUID}
88 | | ${in_container}= | Running in Container | ${nodes['${dut}']}
89 | | ${root}= | Run Keyword If | ${in_container}
90 | | ... | Get Docker Mergeddir | ${nodes['DUT1']}
91 | | ... | ELSE | Set Variable | ${EMPTY}
92 | | ${node_arch}= | Get Node Arch | ${nodes['${dut}']}
93 | | ${name}= | Set Variable | ${dut}_${container_group}${nf_id}${DUT1_UUID}
94 | | ${mnt}= | Create List
95 | | ... | ${root}/tmp/:/mnt/host/
96 | | ... | ${root}/tmp/vpp_sockets/${name}/:/run/vpp/
97 | | ... | ${root}/dev/vfio/:/dev/vfio/
98 | | ... | ${root}/usr/bin/vpp:/usr/bin/vpp
99 | | ... | ${root}/usr/bin/vppctl:/usr/bin/vppctl
100 | | ... | ${root}/usr/lib/${node_arch}-linux-gnu/:/usr/lib/${node_arch}-linux-gnu/
101 | | ... | ${root}/usr/share/vpp/:/usr/share/vpp/
102 | | ${nf_cpus}= | Set Variable | ${None}
103 | | ${nf_cpus}= | Run Keyword If | ${pinning}
104 | | ... | Get Affinity NF | ${nodes} | ${dut}
105 | | ... | nf_chains=${nf_chains} | nf_nodes=${nf_nodes}
106 | | ... | nf_chain=${nf_chain} | nf_node=${nf_node}
107 | | ... | vs_dtc=${cpu_count_int} | nf_dtc=${nf_dtc} | nf_dtcr=${nf_dtcr}
108 | | &{cont_args}= | Create Dictionary
109 | | ... | name=${name} | node=${nodes['${dut}']} | mnt=${mnt} | env=${env}
110 | | ... | root=${root} | page_size=${page_size}
111 | | Run Keyword If | ${pinning}
112 | | ... | Set To Dictionary | ${cont_args} | cpuset_cpus=${nf_cpus}
113 | | Run Keyword | ${container_group}.Construct container | &{cont_args}
114
115 | Construct chain of containers
116 | | [Documentation] | Construct 1 chain of 1..N CNFs on selected/all DUT nodes.
117 | |
118 | | ... | *Arguments:*
119 | | ... | - dut: DUT node to start the containers on. Run on all nodes if None.
120 | | ... | Type: string or None
121 | | ... | - nf_chains: Total number of chains. Type: integer
122 | | ... | - nf_nodes: Total number of nodes per chain. Type: integer
123 | | ... | - nf_chain: Chain ID. Type: integer
124 | | ... | - auto_scale - If True, use same amount of Dataplane threads for
125 | | ... | network function as DUT, otherwise use single physical core for
126 | | ... | every network function. Type: boolean
127 | | ... | - pinning: Set True if CPU pinning should be done on starting
128 | | ... | containers. Type: boolean, default value: ${False}
129 | |
130 | | ... | *Example:*
131 | |
132 | | ... | \| Construct chain of containers \| 1 \| 1 \| 1 \| ${True} \|
133 | |
134 | | [Arguments] | ${dut}=${None} | ${nf_chains}=${1} | ${nf_nodes}=${1}
135 | | ... | ${nf_chain}=${1} | ${auto_scale}=${True} | ${pinning}=${True}
136 | |
137 | | FOR | ${nf_node} | IN RANGE | 1 | ${nf_nodes}+1
138 | | | Run Keyword If | '${dut}' == '${None}'
139 | | | ... | Construct container on all DUTs
140 | | | ... | nf_chains=${nf_chains} | nf_nodes=${nf_nodes} | nf_chain=${nf_chain}
141 | | | ... | nf_node=${nf_node} | auto_scale=${auto_scale} | pinning=${pinning}
142 | | | ... | ELSE
143 | | | ... | Construct container on DUT | ${dut}
144 | | | ... | nf_chains=${nf_chains} | nf_nodes=${nf_nodes} | nf_chain=${nf_chain}
145 | | | ... | nf_node=${nf_node} | auto_scale=${auto_scale} | pinning=${pinning}
146 | | END
147
148 | Construct chains of containers
149 | | [Documentation] | Construct 1..N chains of 1..N CNFs on selected/all DUT
150 | | ... | nodes.
151 | |
152 | | ... | *Arguments:*
153 | | ... | - dut: DUT node to start the containers on. Run on all nodes if None.
154 | | ... | Type: string or None
155 | | ... | - nf_chains: Total number of chains (Optional). Type: integer, default
156 | | ... | value: ${1}
157 | | ... | - nf_nodes: Total number of nodes per chain (Optional). Type: integer,
158 | | ... | default value: ${1}
159 | | ... | - auto_scale - If True, use same amount of Dataplane threads for
160 | | ... | network function as DUT, otherwise use single physical core for
161 | | ... | every network function. Type: boolean
162 | | ... | - pinning: Set True if CPU pinning should be done on starting
163 | | ... | containers. Type: boolean, default value: ${True}
164 | |
165 | | ... | *Example:*
166 | |
167 | | ... | \| Construct chains of containers \| 1 \| 1 \|
168 | |
169 | | [Arguments] | ${dut}=${None} | ${nf_chains}=${1} | ${nf_nodes}=${1}
170 | | ... | ${auto_scale}=${True} | ${pinning}=${True}
171 | |
172 | | FOR | ${nf_chain} | IN RANGE | 1 | ${nf_chains}+1
173 | | | Construct chain of containers
174 | | | ... | dut=${dut} | nf_chains=${nf_chains} | nf_nodes=${nf_nodes}
175 | | | ... | nf_chain=${nf_chain} | auto_scale=${auto_scale} | pinning=${pinning}
176 | | END
177
178 | Acquire all '${group}' containers
179 | | [Documentation] | Acquire all container(s) in specific container group on
180 | | ... | all DUT nodes.
181 | |
182 | | Run Keyword | ${group}.Acquire all containers
183
184 | Create all '${group}' containers
185 | | [Documentation] | Create/deploy all container(s) in specific container group
186 | | ... | on all DUT nodes.
187 | |
188 | | Run Keyword | ${group}.Create all containers
189
190 | Start VPP in all '${group}' containers
191 | | [Documentation] | Start VPP on all container(s) in specific container
192 | | ... | group on all DUT nodes.
193 | |
194 | | Run Keyword | ${group}.Start VPP In All Containers
195
196 | Restart VPP in all '${group}' containers
197 | | [Documentation] | Restart VPP on all container(s) in specific container
198 | | ... | group on all DUT nodes.
199 | |
200 | | Run Keyword | ${group}.Restart VPP In All Containers
201
202 | Configure VPP in all '${group}' containers
203 | | [Documentation] | Configure VPP on all container(s) in specific container
204 | | ... | group on all DUT nodes.
205 | |
206 | | ... | *Test (or broader scope) variables read:*
207 | | ... | - container_chain_topology - Topology type used for configuring CNF
208 | | ... | (VPP) in container. Type: string
209 | |
210 | | ${dut1_if2} = | Get Variable Value | \${dut1_if2} | ${None}
211 | | ${dut2_if2} = | Get Variable Value | \${dut2_if2} | ${None}
212 | | Run Keyword If | '${container_chain_topology}' == 'chain_ip4'
213 | | ... | ${group}.Configure VPP In All Containers
214 | | ... | ${container_chain_topology}
215 | | ... | tg_pf1_mac=${TG_pf1_mac}[0]
216 | | ... | tg_pf2_mac=${TG_pf2_mac}[0]
217 | | ... | nodes=${nf_nodes}
218 | | ... | ELSE IF | '${container_chain_topology}' == 'chain_ipsec'
219 | | ... | ${group}.Configure VPP In All Containers
220 | | ... | ${container_chain_topology}
221 | | ... | tg_pf1_ip4=${tg_if1_ip4}
222 | | ... | tg_pf1_mac=${TG_pf1_mac}[0]
223 | | ... | tg_pf2_ip4=${tg_if2_ip4}
224 | | ... | tg_pf2_mac=${TG_pf2_mac}[0]
225 | | ... | dut1_if1_ip4=${dut1_if1_ip4}
226 | | ... | dut1_if2_ip4=${dut1_if2_ip4}
227 | | ... | dut2_if1_ip4=${dut2_if1_ip4}
228 | | ... | dut2_if2_ip4=${dut2_if2_ip4}
229 | | ... | raddr_ip4=${raddr_ip4}
230 | | ... | laddr_ip4=${laddr_ip4}
231 | | ... | nodes=${nodes}
232 | | ... | nf_nodes=${nf_nodes}
233 | | ... | ELSE IF | '${container_chain_topology}' == 'pipeline_ip4'
234 | | ... | ${group}.Configure VPP In All Containers
235 | | ... | ${container_chain_topology}
236 | | ... | tg_pf1_mac=${TG_pf1_mac}[0]
237 | | ... | tg_pf2_mac=${TG_pf2_mac}[0]
238 | | ... | nodes=${nf_nodes}
239 | | ... | ELSE IF | '${container_chain_topology}' == 'cross_horiz'
240 | | ... | ${group}.Configure VPP In All Containers
241 | | ... | ${container_chain_topology}
242 | | ... | dut1_if=${DUT1_${int}2}[0]
243 | | ... | dut2_if=${DUT2_${int}2}[0]
244 | | ... | ELSE
245 | | ... | ${group}.Configure VPP In All Containers
246 | | ... | ${container_chain_topology}
247
248 | Stop all '${group}' containers
249 | | [Documentation] | Stop all container(s) in specific container group on all
250 | | ... | DUT nodes.
251 | |
252 | | Run Keyword | ${group}.Stop all containers
253
254 | Destroy all '${group}' containers
255 | | [Documentation] | Destroy all container(s) in specific container group on
256 | | ... | all DUT nodes.
257 | |
258 | | Run Keyword | ${group}.Destroy all containers
259
260 | Verify VPP in all '${group}' containers
261 | | [Documentation] | Verify that VPP is running inside containers in specific
262 | | ... | container group on all DUT nodes. Does 120 retries with one second
263 | | ... | between retries.
264 | |
265 | | Run Keyword | ${group}.Verify VPP in all containers
266
267 | Start containers for test
268 | | [Documentation]
269 | | ... | Start containers for test.
270 | |
271 | | ... | *Arguments:*
272 | | ... | - dut: DUT node to start the containers on. Run on all nodes if None.
273 | | ... | Type: string or None
274 | | ... | - nf_chains: Total number of chains. Type: integer
275 | | ... | - nf_nodes: Total number of nodes per chain. Type: integer
276 | | ... | - auto_scale - If True, use same amount of Dataplane threads for
277 | | ... | network function as DUT, otherwise use single physical core for
278 | | ... | every network function. Type: boolean
279 | | ... | - pinning: Set True if CPU pinning should be done on starting
280 | | ... | containers. Type: boolean, default value: ${False}
281 | |
282 | | ... | *Example:*
283 | |
284 | | ... | \| Start containers for test \| 1 \| 1 \|
285 | |
286 | | [Arguments] | ${dut}=${None} | ${nf_chains}=${1} | ${nf_nodes}=${1}
287 | | ... | ${auto_scale}=${True} | ${pinning}=${True}
288 | |
289 | | Set Test Variable | @{container_groups} | @{EMPTY}
290 | | Set Test Variable | ${container_group} | CNF
291 | | Set Test Variable | ${nf_nodes}
292 | | Import Library | resources.libraries.python.ContainerUtils.ContainerManager
293 | | ... | engine=${container_engine} | WITH NAME | ${container_group}
294 | | Construct chains of containers
295 | | ... | dut=${dut} | nf_chains=${nf_chains} | nf_nodes=${nf_nodes}
296 | | ... | auto_scale=${auto_scale} | pinning=${pinning}
297 | | Acquire all '${container_group}' containers
298 | | Create all '${container_group}' containers
299 | | Configure VPP in all '${container_group}' containers
300 | | Start VPP in all '${container_group}' containers
301 | | Append To List | ${container_groups} | ${container_group}
302 | | Save VPP PIDs
303
304 # TODO: Remove the vswitch startup.conf and read the host configuration instead.
305 | Start vswitch in container on DUT
306 | | [Documentation]
307 | | ... | Configure and start vswitch in container.
308 | |
309 | | ... | *Arguments:*
310 | | ... | - dut: DUT node on which to install vswitch. Type: string
311 | | ... | - phy_cores - Number of physical cores to use. Type: integer
312 | | ... | - rx_queues: Number of RX queues. Type: integer
313 | |
314 | | ... | *Example:*
315 | |
316 | | ... | \| Start vswitch in container on DUT \| DUT1 \| 1 \| 1 \|
317 | |
318 | | [Arguments] | ${dut} | ${phy_cores} | ${rx_queues}=${None}
319 | |
320 | | Set Test Variable | ${container_group} | VSWITCH
321 | | Import Library | resources.libraries.python.ContainerUtils.ContainerManager
322 | | ... | engine=${container_engine} | WITH NAME | VSWITCH
323 | | Construct container on DUT | ${dut}
324 | | ... | nf_chains=${1} | nf_nodes=${1} | nf_chain=${1}
325 | | ... | nf_node=${1} | auto_scale=${False} | pinning=${False}
326 | | Acquire all '${container_group}' containers
327 | | Create all '${container_group}' containers
328 | | ${cpu_count_int} | Convert to Integer | ${phy_cores}
329 | | ${dp_count_int} | Convert to Integer | ${phy_cores}
330 | | ${smt_used}= | Is SMT enabled | ${nodes['${dut}']['cpuinfo']}
331 | | ${dp_count_int}= | Run keyword if | ${smt_used}
332 | | ... | Evaluate | int(${cpu_count_int}*2)
333 | | ... | ELSE | Set variable | ${dp_count_int}
334 | | ${rxq_ratio} = | Get Variable Value | \${rxq_ratio} | ${1}
335 | | ${rxq_count_int}= | Run Keyword If | ${rx_queues}
336 | | ... | Set variable | ${rx_queues}
337 | | ... | ELSE | Evaluate | int(${dp_count_int}/${rxq_ratio})
338 | | ${rxq_count_int}= | Run keyword if | ${rxq_count_int} == 0
339 | | ... | Set variable | ${1}
340 | | ... | ELSE | Set variable | ${rxq_count_int}
341 | | VSWITCH.Configure VPP in all containers | chain_vswitch
342 | | ... | rxq=${rxq_count_int} | n_instances=${n_instances} | node=${dut}
343 | | ... | dut1_if1=${DUT1_${int}1}[0] | dut1_if2=${DUT1_${int}2}[0]
344 | | ... | dut2_if1=${DUT2_${int}1}[0] | dut2_if2=${DUT2_${int}2}[0]
345 | | ... | dut2_if2_ip4=${dut2_if2_ip4}
346 | | ... | tg_pf1_ip4=${tg_if1_ip4} | tg_pf1_mac=${TG_pf1_mac}[0]
347 | | ... | tg_pf2_ip4=${tgi_f2_ip4} | tg_pf2_mac=${TG_pf2_mac}[0]
348 | | ... | nodes=${nodes}
349 | | Start VPP in all '${container_group}' containers
350
351 | Start vswitch in container
352 | | [Documentation]
353 | | ... | Configure and start vswitch in container on all DUTs.
354 | |
355 | | ... | *Arguments:*
356 | | ... | - phy_cores - Number of physical cores to use. Type: integer
357 | | ... | - rx_queues: Number of RX queues. Type: integer
358 | |
359 | | ... | *Example:*
360 | |
361 | | ... | \| Start vswitch in container \| 1 \| 1 \|
362 | |
363 | | [Arguments] | ${phy_cores} | ${rx_queues}=${None}
364 | |
365 | | FOR | ${dut} | IN | @{duts}
366 | | | Run Keyword | Start vswitch in container on DUT
367 | | | ... | ${dut} | ${phy_cores} | ${rx_queues}
368 | | END
369 | | Append To List | ${container_groups} | ${container_group}
370 | | Save VPP PIDs