summaryrefslogtreecommitdiffstats
path: root/docker/scripts/lib_csit.sh
blob: 2e877f803769e853704a47c712747927fca614fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
# lib_csit.sh - Docker build script CSIT library.
#               For import only.

# Copyright (c) 2023 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Don't import more than once.
if [ -n "$(alias lib_csit_imported 2> /dev/null)" ] ; then
    return 0
fi
alias lib_csit_imported=true

export CIMAN_DOCKER_SCRIPTS="${CIMAN_DOCKER_SCRIPTS:-$(dirname ${BASH_SOURCE[0]})}"
. "$CIMAN_DOCKER_SCRIPTS/lib_common.sh"
. "$CIMAN_DOCKER_SCRIPTS/lib_apt.sh"

CSIT_SUPPORTED_EXECUTOR_CLASSES="builder csit_dut"
csit_supported_executor_class() {
    if ! grep -q "${1:-}" <<< "$CSIT_SUPPORTED_EXECUTOR_CLASSES" ; then
        return 1
    fi
    return 0
}

csit_supported_os() {
    case "$1" in
        ubuntu-22.04) return 0 ;;
                   *) ;;
    esac
    return 1
}

csit_checkout_branch_for_vpp() {
    local vpp_branch="$1"
    local csit_dir="$DOCKER_CSIT_DIR"
    local csit_bash_function_dir="$csit_dir/resources/libraries/bash/function"

    # import checkout_csit_for_vpp() if not defined
    set +e && [ -z "$(declare -f checkout_csit_for_vpp)" ] \
        && source "$csit_bash_function_dir/branch.sh"
    CSIT_DIR="$csit_dir" checkout_csit_for_vpp "$vpp_branch"

    # shellcheck disable=SC2034,SC2063
    csit_branch="$(git branch | grep -e '^*' | mawk '{print $2}')"
}

csit_install_packages() {
    local branch="$1"
    local branchname
    branchname="$(echo $branch | sed -e 's,/,_,')"
    local csit_dir="$DOCKER_CSIT_DIR"
    local csit_ansible_dir="$csit_dir/fdio.infra.ansible"
    if [ ! -d "$csit_ansible_dir" ] ; then
        csit_ansible_dir="$csit_dir/resources/tools/testbed-setup/ansible"
    fi
    local bld_log="$DOCKER_BUILD_LOG_DIR/$FDIOTOOLS_IMAGENAME"
    bld_log="${bld_log}-$branchname-csit_install_packages-bld.log"

    git clean -qfdx
    python3 -m pip install pyyaml

    local exclude_roles="-e calibration -e kernel -e mellanox -e nomad -e consul -e aws -e vpp"
    [ "$OS_ARCH" = "aarch64" ] && exclude_roles="$exclude_roles -e iperf"

    # Not in double quotes to let bash remove newline characters
    local yaml_files
    yaml_files="$(grep -r packages_by $csit_ansible_dir | cut -d: -f1 | sort -u | grep -v $exclude_roles)"
    packages="$(dbld_csit_find_ansible_packages.py --$OS_ID --$OS_ARCH $yaml_files)"
    packages="${packages/jammy /}"
    packages="${packages/focal /}"
    packages="${packages/libmbedcrypto1/libmbedcrypto3}"
    packages="${packages/libmbedtls10/libmbedtls12}"
    packages="$(echo ${packages//python\-/python3\-} | tr ' ' '\n' | sort -u | xargs)"

    if [ -n "$packages" ] ; then
        case "$OS_NAME" in
            ubuntu*)
                apt_install_packages "$packages" 2>&1 | tee -a "$bld_log"
                ;;
            debian*)
                apt_install_packages "$packages" 2>&1 | tee -a "$bld_log"
                ;;
            *)
                echo "Unsupported OS ($OS_ID): CSIT packages NOT INSTALLED!"
                ;;
        esac
    fi
}

csit_install_hugo() {
    local branch="$1"
    CSIT_DIR="$DOCKER_CSIT_DIR"

    if [ -f "$CSIT_DIR/VPP_REPO_URL" ] \
           && [ -f "$CSIT_DIR/requirements.txt" ]; then

        local branchname
        # use bash variable substitution to replace '/' with '_' to convert from
        # vpp to csit branch name nomenclature
        branchname="${branch////_}"
        local csit_bash_function_dir="$CSIT_DIR/resources/libraries/bash/function"
        local bld_log="$DOCKER_BUILD_LOG_DIR"
        bld_log="${bld_log}/$FDIOTOOLS_IMAGENAME-$branchname-csit_install_hugo-bld.log"

        description="Install CSIT hugo packages from $branch branch"
        echo_log "    Starting  $description..."
        git clean -qfdx

        source "$csit_bash_function_dir"/hugo.sh
        go_install 2>&1 | tee -a "$bld_log"
        hugo_install 2>&1 | tee -a "$bld_log"

    else
        echo_log "ERROR: Missing or invalid CSIT_DIR: '$CSIT_DIR'!"
        return 1
    fi
}

csit_pip_cache() {
    local branch="$1"
    # ensure PS1 is defined (used by virtualenv activate script)
    PS1=${PS1:-"#"}
    CSIT_DIR="$DOCKER_CSIT_DIR"

    if [ -f "$CSIT_DIR/VPP_REPO_URL" ] \
           && [ -f "$CSIT_DIR/requirements.txt" ]; then

        local branchname
        # use bash variable substitution to replace '/' with '_' to convert from
        # vpp to csit branch name nomenclature
        branchname="${branch////_}"
        local csit_bash_function_dir="$CSIT_DIR/resources/libraries/bash/function"
        local bld_log="$DOCKER_BUILD_LOG_DIR"
        bld_log="${bld_log}/$FDIOTOOLS_IMAGENAME-$branchname-csit_pip_cache-bld.log"
        export PYTHONPATH=$CSIT_DIR

        description="Install CSIT python packages from $branch branch"
        echo_log "    Starting  $description..." 2>&1 | tee -a "$bld_log"
        git clean -qfdx 2>&1 | tee -a "$bld_log"
        rm -rf "$PYTHONPATH/env"

        # Activate / install CSIT python virtualenv ($CSIT_DIR/requirements.txt)
        local common_sh="$csit_bash_function_dir/common.sh"
        # shellcheck disable=1090
        source "$common_sh"
        activate_virtualenv "${CSIT_DIR}" "${CSIT_DIR}/requirements.txt" 2>&1 | tee -a "$bld_log"

        # Install tox python requirements
        activate_virtualenv "${CSIT_DIR}" "${CSIT_DIR}/tox-requirements.txt" 2>&1 |\
            tee -a "$bld_log"

        # Clean up virtualenv directories
        git checkout -q -- .
        git clean -qfdx
        echo_log "    Completed $description!" 2>&1 | tee -a "$bld_log"
    else
        echo_log "ERROR: Missing or invalid CSIT_DIR: '$CSIT_DIR'!"
        return 1
    fi
}

docker_build_setup_csit() {
    if csit_supported_executor_class "$EXECUTOR_CLASS" ; then
        if [ ! -d "$DOCKER_CSIT_DIR" ] ; then
            echo_log "Cloning CSIT into $DOCKER_CSIT_DIR..."
            git clone -q https://gerrit.fd.io/r/csit "$DOCKER_CSIT_DIR"
        fi
        clean_git_repo "$DOCKER_CSIT_DIR"
    fi
}

csit_dut_generate_docker_build_files() {
    local build_files_dir="$DOCKER_BUILD_FILES_DIR"

    mkdir -p "$build_files_dir"
    cat <<EOF >"$build_files_dir/supervisord.conf"
[unix_http_server]
file = /tmp/supervisor.sock
chmod = 0777

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl = unix:///tmp/supervisor.sock

[supervisord]
pidfile = /tmp/supervisord.pid
identifier = supervisor
directory = /tmp
logfile = /tmp/supervisord.log
loglevel = debug
nodaemon = false

[program:vpp]
command = /usr/bin/vpp -c /etc/vpp/startup.conf
autostart = false
autorestart = true
redirect_stderr = true
priority = 1
EOF
}

csit_builder_generate_docker_build_files() {
    local build_files_dir="$DOCKER_BUILD_FILES_DIR"
    local dashes="-----"
    local dbeg="${dashes}BEGIN"
    local dend="${dashes}END"
    local pvt="PRIVATE"
    local kd="KEY$dashes"

    # TODO: Verify why badkey is required & figure out how to avoid it.
    mkdir -p "$build_files_dir"
    cat <<EOF >"$build_files_dir/badkey"
$dbeg RSA $pvt $kd
MIIEowIBAAKCAQEAslDXf4kZOQI8OGQQdIF8o83nBM0B4fzHLYLxxiY2rKiQ5MGM
mQa7p1KKzmd5/NlvFRnXefnjSDQljjPxEY7mh457rX2nXvqHD4GUXZPpBIE73rQ1
TViIAXdDzFXJ6ee4yX8ewmVakzYBnlUPDidkWyRnjm/xCgKUCO+CD5AH3ND0onks
OYAtHqhDh29/QMIKdMnK87FBxfzhInHwpqPur76zBnpw3u36ylKEymDFrO5dwzsh
QvDWjsYRg9ydTXubtwP6+MOpjdR1SNKxcCHKJrPrdAeJW9jg1imYmYpEHZ/P3qsL
Jm0hGWbFjdxZLIYIz0vN/nTalcAeqT2OWKrXuwIDAQABAoIBAQCcj1g2FOR9ZlYD
WPANqucJVy4/y9OcXHlwnyiyRjj47WOSRdGxRfUa2uEeikHT3ACo8TB8WwfQDGDw
8u/075e+az5xvAJo5OQSnD3sz4Hmv6UWSvkFuPZo+xMe5C/M2/QljiQuoBifaeqP
3rTCQ5ncYCFAMU7b8BmTot551Ybhu2jCbDMHU7nFHEFOvYinkwfVcaqkrVDUuH+D
c3NkAEH9Jz2MEYA2Va4uqFpGt5lfGiED2kMenwPa8eS5LS5HJsxkfMHGlaHXHFUb
D+dG/qJtSslVxdzVPgEGvzswo6TgtY1nZTQcB8U63rktFg38B7QGtOkvswAYzxyk
HdMIiU3RAoGBAOdIEQRcAThj9eiIFywtBgLBOSg4SoOnvELLr6lgUg2+ICmx06LQ
yaai1QRdOWw1VwZ6apNCD00kaUhBu+ou93yLSDnR2uYftkylhcnVuhDyIeNyb81V
hV2z0WuNv3aKBFlBxaq391S7WW1XxhpAAagm8fZZur73wV390EVd/hZJAoGBAMVf
negT2bg5PVKWvsiEU6eZ00W97tlEDLclkiZawXNnM2/c+2x1Tks6Yf1E/j2FFTB4
r0fesbwN346hCejtq5Bup5YEdFA3KtwT5UyeQQLFGYlCtRmBtOd10wkRS93D0tpX
iIqkf43Gpx6iFdvBWY5A7N+ZmojCy9zpL5TJ4G3jAoGADOGEoRuGrd9TWMoLkFhJ
l2mvhz/rVn3HDGlPtT06FK3cGLZgtRavxGoZNw8CHbayzBeRS/ZH5+H5Qx72GkrX
WcZgFWhMqrhlbMtjMiSHIl556LL86xCyRs+3ACh6211AdMAnBCUOz1dH2cEjtV6P
ORBCNZg1wGEIEfYK3XIorpECgYBubXfQj8KhUs0fdx3Y3Ehdni/ZdlG7F1qx4YBq
mx5e7d+Wd6Hn5Z3fcxO9+yrvypS3YN5YrJzuZSiuCSWdP9RcY7y5r1ZQRv1g0nTZ
MDWZUiNea4cddTd8xKxFB3tV4SkIZi8LustuzDVWa0Mlh4EOmP6uf6c5WxtqRsEL
UwORFwKBgEjZsfmZGBurjOtSrcsteulOB0D2nOqPVRWXmbSNJT/l73DkEllvVyA/
wdW39nyFrA2Qw1K2F+l8DkzMd/WEjmioSWCsvTkXlvrqPfByKg01zCbYy/mhRW7d
7sQrPOIl8ygsc3JrxmvzibdWmng1MehvpAM1ogWeTUa1lsDTNJ/6
$dend RSA $pvt $kd
EOF
    chmod 600 "$build_files_dir/badkey"
    cat <<EOF >"$build_files_dir/sshconfig"
Host 172.17.0.*
        StrictHostKeyChecking no
        UserKnownHostsFile=/dev/null
EOF
}

csit_shim_generate_docker_build_files() {
    local build_files_dir="$DOCKER_BUILD_FILES_DIR"
    # TODO: Verify why badkey is required & figure out how to avoid it.
    local badkey='AAAAB3NzaC1yc2EAAAADAQABAAABAQCyUNd/iRk5Ajw4ZBB0gXyjzecEzQHh/MctgvHGJjasqJDkwYyZBrunUorOZ3n82W8VGdd5+eNINCWOM/ERjuaHjnutfade+ocPgZRdk+kEgTvetDVNWIgBd0PMVcnp57jJfx7CZVqTNgGeVQ8OJ2RbJGeOb/EKApQI74IPkAfc0PSieSw5gC0eqEOHb39Awgp0ycrzsUHF/OEicfCmo+6vvrMGenDe7frKUoTKYMWs7l3DOyFC8NaOxhGD3J1Ne5u3A/r4w6mN1HVI0rFwIcoms+t0B4lb2ODWKZiZikQdn8/eqwsmbSEZZsWN3FkshgjPS83+dNqVwB6pPY5Yqte7'

    mkdir -p "$build_files_dir"
    # TODO: Verify why badkeypub is required & figure out how to avoid it.
    echo "ssh-rsa $badkey ejk@bhima.local" >"$build_files_dir/badkeypub"

    cat <<EOF >"$build_files_dir/sshconfig"
Host 172.17.0.*
        StrictHostKeyChecking no
        UserKnownHostsFile=/dev/null
EOF
    cat <<EOF >"$build_files_dir/wrapdocker"
#!/bin/bash

# Ensure that all nodes in /dev/mapper correspond to mapped devices currently loaded by the device-mapper kernel driver
dmsetup mknodes

# First, make sure that cgroups are mounted correctly.
CGROUP=/sys/fs/cgroup
: {LOG:=stdio}

[ -d \$CGROUP ] ||
    mkdir \$CGROUP

mountpoint -q \$CGROUP ||
    mount -n -t tmpfs -o uid=0,gid=0,mode=0755 cgroup \$CGROUP || {
        echo "Could not make a tmpfs mount. Did you use --privileged?"
        exit 1
    }

if [ -d /sys/kernel/security ] && ! mountpoint -q /sys/kernel/security
then
    mount -t securityfs none /sys/kernel/security || {
        echo "Could not mount /sys/kernel/security."
        echo "AppArmor detection and --privileged mode might break."
    }
fi

# Mount the cgroup hierarchies exactly as they are in the parent system.
for SUBSYS in \$(cut -d: -f2 /proc/1/cgroup)
do
        [ -d \$CGROUP/\$SUBSYS ] || mkdir \$CGROUP/\$SUBSYS
        mountpoint -q \$CGROUP/\$SUBSYS ||
                mount -n -t cgroup -o \$SUBSYS cgroup \$CGROUP/\$SUBSYS

        # The two following sections address a bug which manifests itself
        # by a cryptic "lxc-start: no ns_cgroup option specified" when
        # trying to start containers withina container.
        # The bug seems to appear when the cgroup hierarchies are not
        # mounted on the exact same directories in the host, and in the
        # container.

        # Named, control-less cgroups are mounted with "-o name=foo"
        # (and appear as such under /proc/<pid>/cgroup) but are usually
        # mounted on a directory named "foo" (without the "name=" prefix).
        # Systemd and OpenRC (and possibly others) both create such a
        # cgroup. To avoid the aforementioned bug, we symlink "foo" to
        # "name=foo". This shouldn't have any adverse effect.
        echo \$SUBSYS | grep -q ^name= && {
                NAME=\$(echo \$SUBSYS | sed s/^name=//)
                ln -s \$SUBSYS \$CGROUP/\$NAME
        }

        # Likewise, on at least one system, it has been reported that
        # systemd would mount the CPU and CPU accounting controllers
        # (respectively "cpu" and "cpuacct") with "-o cpuacct,cpu"
        # but on a directory called "cpu,cpuacct" (note the inversion
        # in the order of the groups). This tries to work around it.
        [ \$SUBSYS = cpuacct,cpu ] && ln -s \$SUBSYS \$CGROUP/cpu,cpuacct
done

# Note: as I write those lines, the LXC userland tools cannot setup
# a "sub-container" properly if the "devices" cgroup is not in its
# own hierarchy. Let's detect this and issue a warning.
grep -q :devices: /proc/1/cgroup ||
    echo "WARNING: the 'devices' cgroup should be in its own hierarchy."
grep -qw devices /proc/1/cgroup ||
    echo "WARNING: it looks like the 'devices' cgroup is not mounted."

# Now, close extraneous file descriptors.
pushd /proc/self/fd >/dev/null
for FD in *
do
    case "\$FD" in
    # Keep stdin/stdout/stderr
    [012])
        ;;
    # Nuke everything else
    *)
        eval exec "\$FD>&-"
        ;;
    esac
done
popd >/dev/null


# If a pidfile is still around (for example after a container restart),
# delete it so that docker can start.
rm -rf /var/run/docker.pid

# If we were given a PORT environment variable, start as a simple daemon;
# otherwise, spawn a shell as well
if [ "\$PORT" ]
then
    exec dockerd -H 0.0.0.0:\$PORT -H unix:///var/run/docker.sock \
        \$DOCKER_DAEMON_ARGS
else
    if [ "\$LOG" == "file" ]
    then
        dockerd \$DOCKER_DAEMON_ARGS &>/var/log/docker.log &
    else
        dockerd \$DOCKER_DAEMON_ARGS &
    fi
    (( timeout = 60 + SECONDS ))
    until docker info >/dev/null 2>&1
    do
        if (( SECONDS >= timeout )); then
            echo 'Timed out trying to connect to internal docker host.' >&2
            break
        fi
        sleep 1
    done
    [[ \$1 ]] && exec "\$@"
    exec bash --login
fi
EOF
}