4b2ad225279b0cf6525a6d99b5564e2cf5ae0c35
[csit.git] / resources / libraries / robot / shared / container.robot
1 # Copyright (c) 2021 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 | | ${root}= | Run Keyword If | ${dut1_uuid_length}
89 | | ... | Get Docker Mergeddir | ${nodes['DUT1']} | ${DUT1_UUID}
90 | | ... | ELSE | Set Variable | ${EMPTY}
91 | | ${node_arch}= | Get Node Arch | ${nodes['${dut}']}
92 | | ${name}= | Set Variable | ${dut}_${container_group}${nf_id}${DUT1_UUID}
93 | | ${mnt}= | Create List
94 | | ... | ${root}/tmp/:/mnt/host/
95 | | ... | ${root}/tmp/vpp_sockets/${name}/:/run/vpp/
96 | | ... | ${root}/dev/vfio/:/dev/vfio/
97 | | ... | ${root}/usr/bin/vpp:/usr/bin/vpp
98 | | ... | ${root}/usr/bin/vppctl:/usr/bin/vppctl
99 | | ... | ${root}/usr/lib/${node_arch}-linux-gnu/:/usr/lib/${node_arch}-linux-gnu/
100 | | ... | ${root}/usr/share/vpp/:/usr/share/vpp/
101 | | ${nf_cpus}= | Set Variable | ${None}
102 | | ${nf_cpus}= | Run Keyword If | ${pinning}
103 | | ... | Get Affinity NF | ${nodes} | ${dut}
104 | | ... | nf_chains=${nf_chains} | nf_nodes=${nf_nodes}
105 | | ... | nf_chain=${nf_chain} | nf_node=${nf_node}
106 | | ... | vs_dtc=${cpu_count_int} | nf_dtc=${nf_dtc} | nf_dtcr=${nf_dtcr}
107 | | &{cont_args}= | Create Dictionary
108 | | ... | name=${name} | node=${nodes['${dut}']} | mnt=${mnt} | env=${env}
109 | | ... | root=${root}
110 | | Run Keyword If | ${pinning}
111 | | ... | Set To Dictionary | ${cont_args} | cpuset_cpus=${nf_cpus}
112 | | Run Keyword | ${container_group}.Construct container | &{cont_args}
113
114 | Construct chain of containers
115 | | [Documentation] | Construct 1 chain of 1..N CNFs on selected/all DUT nodes.
116 | |
117 | | ... | *Arguments:*
118 | | ... | - dut: DUT node to start the containers on. Run on all nodes if None.
119 | | ... | Type: string or None
120 | | ... | - nf_chains: Total number of chains. Type: integer
121 | | ... | - nf_nodes: Total number of nodes per chain. Type: integer
122 | | ... | - nf_chain: Chain ID. Type: integer
123 | | ... | - auto_scale - If True, use same amount of Dataplane threads for
124 | | ... | network function as DUT, otherwise use single physical core for
125 | | ... | every network function. Type: boolean
126 | | ... | - pinning: Set True if CPU pinning should be done on starting
127 | | ... | containers. Type: boolean, default value: ${False}
128 | |
129 | | ... | *Example:*
130 | |
131 | | ... | \| Construct chain of containers \| 1 \| 1 \| 1 \| ${True} \|
132 | |
133 | | [Arguments] | ${dut}=${None} | ${nf_chains}=${1} | ${nf_nodes}=${1}
134 | | ... | ${nf_chain}=${1} | ${auto_scale}=${True} | ${pinning}=${True}
135 | |
136 | | FOR | ${nf_node} | IN RANGE | 1 | ${nf_nodes}+1
137 | | | Run Keyword If | '${dut}' == '${None}'
138 | | | ... | Construct container on all DUTs
139 | | | ... | nf_chains=${nf_chains} | nf_nodes=${nf_nodes} | nf_chain=${nf_chain}
140 | | | ... | nf_node=${nf_node} | auto_scale=${auto_scale} | pinning=${pinning}
141 | | | ... | ELSE
142 | | | ... | Construct container on DUT | ${dut}
143 | | | ... | nf_chains=${nf_chains} | nf_nodes=${nf_nodes} | nf_chain=${nf_chain}
144 | | | ... | nf_node=${nf_node} | auto_scale=${auto_scale} | pinning=${pinning}
145 | | END
146
147 | Construct chains of containers
148 | | [Documentation] | Construct 1..N chains of 1..N CNFs on selected/all DUT
149 | | ... | nodes.
150 | |
151 | | ... | *Arguments:*
152 | | ... | - dut: DUT node to start the containers on. Run on all nodes if None.
153 | | ... | Type: string or None
154 | | ... | - nf_chains: Total number of chains (Optional). Type: integer, default
155 | | ... | value: ${1}
156 | | ... | - nf_nodes: Total number of nodes per chain (Optional). Type: integer,
157 | | ... | default value: ${1}
158 | | ... | - auto_scale - If True, use same amount of Dataplane threads for
159 | | ... | network function as DUT, otherwise use single physical core for
160 | | ... | every network function. Type: boolean
161 | | ... | - pinning: Set True if CPU pinning should be done on starting
162 | | ... | containers. Type: boolean, default value: ${True}
163 | |
164 | | ... | *Example:*
165 | |
166 | | ... | \| Construct chains of containers \| 1 \| 1 \|
167 | |
168 | | [Arguments] | ${dut}=${None} | ${nf_chains}=${1} | ${nf_nodes}=${1}
169 | | ... | ${auto_scale}=${True} | ${pinning}=${True}
170 | |
171 | | FOR | ${nf_chain} | IN RANGE | 1 | ${nf_chains}+1
172 | | | Construct chain of containers
173 | | | ... | dut=${dut} | nf_chains=${nf_chains} | nf_nodes=${nf_nodes}
174 | | | ... | nf_chain=${nf_chain} | auto_scale=${auto_scale} | pinning=${pinning}
175 | | END
176
177 | Acquire all '${group}' containers
178 | | [Documentation] | Acquire all container(s) in specific container group on
179 | | ... | all DUT nodes.
180 | |
181 | | Run Keyword | ${group}.Acquire all containers
182
183 | Create all '${group}' containers
184 | | [Documentation] | Create/deploy all container(s) in specific container group
185 | | ... | on all DUT nodes.
186 | |
187 | | Run Keyword | ${group}.Create all containers
188
189 | Start VPP in all '${group}' containers
190 | | [Documentation] | Start VPP on all container(s) in specific container
191 | | ... | group on all DUT nodes.
192 | |
193 | | Run Keyword | ${group}.Start VPP In All Containers
194
195 | Restart VPP in all '${group}' containers
196 | | [Documentation] | Restart VPP on all container(s) in specific container
197 | | ... | group on all DUT nodes.
198 | |
199 | | Run Keyword | ${group}.Restart VPP In All Containers
200
201 | Configure VPP in all '${group}' containers
202 | | [Documentation] | Configure VPP on all container(s) in specific container
203 | | ... | group on all DUT nodes.
204 | |
205 | | ... | *Test (or broader scope) variables read:*
206 | | ... | - container_chain_topology - Topology type used for configuring CNF
207 | | ... | (VPP) in container. Type: string
208 | |
209 | | ${dut1_if2} = | Get Variable Value | \${dut1_if2} | ${None}
210 | | ${dut2_if2} = | Get Variable Value | \${dut2_if2} | ${None}
211 | | Run Keyword If | '${container_chain_topology}' == 'chain_ip4'
212 | | ... | ${group}.Configure VPP In All Containers
213 | | ... | ${container_chain_topology}
214 | | ... | tg_pf1_mac=${TG_pf1_mac}[0]
215 | | ... | tg_pf2_mac=${TG_pf2_mac}[0]
216 | | ... | nodes=${nf_nodes}
217 | | ... | ELSE IF | '${container_chain_topology}' == 'chain_ipsec'
218 | | ... | ${group}.Configure VPP In All Containers
219 | | ... | ${container_chain_topology}
220 | | ... | tg_pf1_ip4=${tg_if1_ip4}
221 | | ... | tg_pf1_mac=${TG_pf1_mac}[0]
222 | | ... | tg_pf2_ip4=${tg_if2_ip4}
223 | | ... | tg_pf2_mac=${TG_pf2_mac}[0]
224 | | ... | dut1_if1_ip4=${dut1_if1_ip4}
225 | | ... | dut1_if2_ip4=${dut1_if2_ip4}
226 | | ... | dut2_if1_ip4=${dut2_if1_ip4}
227 | | ... | dut2_if2_ip4=${dut2_if2_ip4}
228 | | ... | raddr_ip4=${raddr_ip4}
229 | | ... | laddr_ip4=${laddr_ip4}
230 | | ... | nodes=${nodes}
231 | | ... | nf_nodes=${nf_nodes}
232 | | ... | ELSE IF | '${container_chain_topology}' == 'pipeline_ip4'
233 | | ... | ${group}.Configure VPP In All Containers
234 | | ... | ${container_chain_topology}
235 | | ... | tg_pf1_mac=${TG_pf1_mac}[0]
236 | | ... | tg_pf2_mac=${TG_pf2_mac}[0]
237 | | ... | nodes=${nf_nodes}
238 | | ... | ELSE IF | '${container_chain_topology}' == 'cross_horiz'
239 | | ... | ${group}.Configure VPP In All Containers
240 | | ... | ${container_chain_topology}
241 | | ... | dut1_if=${DUT1_${int}2}[0]
242 | | ... | dut2_if=${DUT2_${int}2}[0]
243 | | ... | ELSE
244 | | ... | ${group}.Configure VPP In All Containers
245 | | ... | ${container_chain_topology}
246
247 | Stop all '${group}' containers
248 | | [Documentation] | Stop all container(s) in specific container group on all
249 | | ... | DUT nodes.
250 | |
251 | | Run Keyword | ${group}.Stop all containers
252
253 | Destroy all '${group}' containers
254 | | [Documentation] | Destroy all container(s) in specific container group on
255 | | ... | all DUT nodes.
256 | |
257 | | Run Keyword | ${group}.Destroy all containers
258
259 | Verify VPP in all '${group}' containers
260 | | [Documentation] | Verify that VPP is running inside containers in specific
261 | | ... | container group on all DUT nodes. Does 120 retries with one second
262 | | ... | between retries.
263 | |
264 | | Run Keyword | ${group}.Verify VPP in all containers
265
266 | Start containers for test
267 | | [Documentation]
268 | | ... | Start containers for test.
269 | |
270 | | ... | *Arguments:*
271 | | ... | - dut: DUT node to start the containers on. Run on all nodes if None.
272 | | ... | Type: string or None
273 | | ... | - nf_chains: Total number of chains. Type: integer
274 | | ... | - nf_nodes: Total number of nodes per chain. Type: integer
275 | | ... | - auto_scale - If True, use same amount of Dataplane threads for
276 | | ... | network function as DUT, otherwise use single physical core for
277 | | ... | every network function. Type: boolean
278 | | ... | - pinning: Set True if CPU pinning should be done on starting
279 | | ... | containers. Type: boolean, default value: ${False}
280 | |
281 | | ... | *Example:*
282 | |
283 | | ... | \| Start containers for test \| 1 \| 1 \|
284 | |
285 | | [Arguments] | ${dut}=${None} | ${nf_chains}=${1} | ${nf_nodes}=${1}
286 | | ... | ${auto_scale}=${True} | ${pinning}=${True}
287 | |
288 | | Set Test Variable | @{container_groups} | @{EMPTY}
289 | | Set Test Variable | ${container_group} | CNF
290 | | Set Test Variable | ${nf_nodes}
291 | | Import Library | resources.libraries.python.ContainerUtils.ContainerManager
292 | | ... | engine=${container_engine} | WITH NAME | ${container_group}
293 | | Construct chains of containers
294 | | ... | dut=${dut} | nf_chains=${nf_chains} | nf_nodes=${nf_nodes}
295 | | ... | auto_scale=${auto_scale} | pinning=${pinning}
296 | | Acquire all '${container_group}' containers
297 | | Create all '${container_group}' containers
298 | | Configure VPP in all '${container_group}' containers
299 | | Start VPP in all '${container_group}' containers
300 | | Append To List | ${container_groups} | ${container_group}
301 | | Save VPP PIDs
302
303 # TODO: Remove the vswitch startup.conf and read the host configuration instead.
304 | Start vswitch in container on DUT
305 | | [Documentation]
306 | | ... | Configure and start vswitch in container.
307 | |
308 | | ... | *Arguments:*
309 | | ... | - dut: DUT node on which to install vswitch. Type: string
310 | | ... | - phy_cores - Number of physical cores to use. Type: integer
311 | | ... | - rx_queues: Number of RX queues. Type: integer
312 | |
313 | | ... | *Example:*
314 | |
315 | | ... | \| Start vswitch in container on DUT \| DUT1 \| 1 \| 1 \|
316 | |
317 | | [Arguments] | ${dut} | ${phy_cores} | ${rx_queues}=${None}
318 | |
319 | | Set Test Variable | ${container_group} | VSWITCH
320 | | Import Library | resources.libraries.python.ContainerUtils.ContainerManager
321 | | ... | engine=${container_engine} | WITH NAME | VSWITCH
322 | | Construct container on DUT | ${dut}
323 | | ... | nf_chains=${1} | nf_nodes=${1} | nf_chain=${1}
324 | | ... | nf_node=${1} | auto_scale=${False} | pinning=${False}
325 | | Acquire all '${container_group}' containers
326 | | Create all '${container_group}' containers
327 | | ${cpu_count_int} | Convert to Integer | ${phy_cores}
328 | | ${dp_count_int} | Convert to Integer | ${phy_cores}
329 | | ${smt_used}= | Is SMT enabled | ${nodes['${dut}']['cpuinfo']}
330 | | ${dp_count_int}= | Run keyword if | ${smt_used}
331 | | ... | Evaluate | int(${cpu_count_int}*2)
332 | | ... | ELSE | Set variable | ${dp_count_int}
333 | | ${rxq_ratio} = | Get Variable Value | \${rxq_ratio} | ${1}
334 | | ${rxq_count_int}= | Run Keyword If | ${rx_queues}
335 | | ... | Set variable | ${rx_queues}
336 | | ... | ELSE | Evaluate | int(${dp_count_int}/${rxq_ratio})
337 | | ${rxq_count_int}= | Run keyword if | ${rxq_count_int} == 0
338 | | ... | Set variable | ${1}
339 | | ... | ELSE | Set variable | ${rxq_count_int}
340 | | VSWITCH.Configure VPP in all containers | chain_vswitch
341 | | ... | rxq=${rxq_count_int} | n_instances=${n_instances} | node=${dut}
342 | | ... | dut1_if1=${DUT1_${int}1}[0] | dut1_if2=${DUT1_${int}2}[0]
343 | | ... | dut2_if1=${DUT2_${int}1}[0] | dut2_if2=${DUT2_${int}2}[0]
344 | | ... | dut2_if2_ip4=${dut2_if2_ip4}
345 | | ... | tg_pf1_ip4=${tg_if1_ip4} | tg_pf1_mac=${TG_pf1_mac}[0]
346 | | ... | tg_pf2_ip4=${tgi_f2_ip4} | tg_pf2_mac=${TG_pf2_mac}[0]
347 | | ... | nodes=${nodes}
348 | | Start VPP in all '${container_group}' containers
349
350 | Start vswitch in container
351 | | [Documentation]
352 | | ... | Configure and start vswitch in container on all DUTs.
353 | |
354 | | ... | *Arguments:*
355 | | ... | - phy_cores - Number of physical cores to use. Type: integer
356 | | ... | - rx_queues: Number of RX queues. Type: integer
357 | |
358 | | ... | *Example:*
359 | |
360 | | ... | \| Start vswitch in container \| 1 \| 1 \|
361 | |
362 | | [Arguments] | ${phy_cores} | ${rx_queues}=${None}
363 | |
364 | | FOR | ${dut} | IN | @{duts}
365 | | | Run Keyword | Start vswitch in container on DUT
366 | | | ... | ${dut} | ${phy_cores} | ${rx_queues}
367 | | END
368 | | Append To List | ${container_groups} | ${container_group}
369 | | Save VPP PIDs