
Currently, the Dockerfile expects /etc/systemd/journald.conf to exist on the base container, but sometimes this may not be the case, for example on Fedora 40, which causes the build process to fail if the host machine is also running Fedora 40. Update the dockerfile to create a conf.d file instead, which has higher precedence. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1972
522 lines
13 KiB
Bash
Executable File
522 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -e
|
|
|
|
###############################################################################
|
|
# Script to create a podman container for testing NetworkManager.
|
|
#
|
|
# Commands:
|
|
# - build: build a new image, named "$CONTAINER_NAME_REPOSITORY:$CONTAINER_NAME_TAG" ("nm:nm").
|
|
# - run: start the container and tag it "$CONTAINER_NAME_NAME" ("nm").
|
|
# - exec: run bash inside the container (this is the default).
|
|
# - journal|j: print the journal from inside the container.
|
|
# - stop: stop the container.
|
|
# - reset: stop and delete the container.
|
|
# - clean: stop and delete the container and the image.
|
|
#
|
|
# Options:
|
|
# --no-cleanup: don't delete the CONTAINERFILE and other artifacts
|
|
# --stop: only has effect with "run". It will stop the container afterwards.
|
|
# -- [EXTRA_ARGS]:
|
|
# - with command "exec", provide a command and arguments to run in the container.
|
|
# Defaults to "bash".
|
|
# - with command "journal", additional arguments that are passed to journalctl.
|
|
#
|
|
# It bind mounts the current working directory inside the container.
|
|
# You can run `make install` and run tests.
|
|
# There is a script nm-env-prepare.sh to generate a net1 interface for testing.
|
|
#
|
|
# This will bind-mount the NetworkManager working tree inside the container (and symlink
|
|
# from /NetworkManager). Create a file ".git/nm-in-container-host" to bind mount the host's
|
|
# "/" to "/Host".
|
|
#
|
|
# Create a symlink ./.git/NetworkManager-ci, to also bind-mount the CI directory.
|
|
# Create additional symlinks ./.git/nm-guest-link-*, to bind mount additional
|
|
# directories.
|
|
#
|
|
# Currently NM-ci requires a working eth1.
|
|
# Hence call `nm-env-prepare.sh --prefix eth -i 1 && sleep 1 && nmcli device connect eth1` before
|
|
# running a CI test.
|
|
###############################################################################
|
|
|
|
if [ -z "$BASE_IMAGE" ]; then
|
|
if grep -q "^ID=fedora$" /etc/os-release 2>/dev/null ; then
|
|
BASE_IMAGE="$(sed -n 's/^VERSION_ID=\([0-9]\+\)$/fedora:\1/p' /etc/os-release)"
|
|
fi
|
|
fi
|
|
if [ -z "$BASE_IMAGE" ]; then
|
|
BASE_IMAGE=fedora:latest
|
|
fi
|
|
|
|
BASEDIR_NM="$(readlink -f "$(dirname "$(readlink -f "$0")")/..")"
|
|
BASEDIR_DATA="$BASEDIR_NM/tools/nm-guest-data"
|
|
|
|
SYMLINK_NAME=()
|
|
SYMLINK_TARGET=()
|
|
for d in $(ls -1d "$BASEDIR_NM/.git/NetworkManager-ci" "$BASEDIR_NM/.git/nm-guest-link-"* 2>/dev/null) ; do
|
|
NAME="${d##*/}"
|
|
NAME="${NAME##nm-guest-link-}"
|
|
TARGET="$(readlink -f "$d")"
|
|
test -e "$TARGET"
|
|
SYMLINK_NAME+=("$NAME")
|
|
SYMLINK_TARGET+=("$TARGET")
|
|
done
|
|
|
|
CONTAINER_NAME_REPOSITORY=${CONTAINER_NAME_REPOSITORY:-nm}
|
|
CONTAINER_NAME_TAG=${CONTAINER_NAME_TAG:-nm}
|
|
CONTAINER_NAME_NAME=${CONTAINER_NAME_NAME:-nm}
|
|
|
|
EXEC_ENV=()
|
|
|
|
###############################################################################
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
$0: build|run|exec|stop|reset|reexec|clean|journal [--no-cleanup] [--stop] [-- EXTRA_ARGS]
|
|
EOF
|
|
echo
|
|
awk '/^####*$/{ if(on) exit; on=1} { if (on) { if (on==2) print(substr($0,3)); on=2; } }' "$BASH_SOURCE"
|
|
echo
|
|
}
|
|
|
|
###############################################################################
|
|
|
|
die() {
|
|
(
|
|
echo -n -e "\033[31m"
|
|
printf "%s" "$*"
|
|
echo -e "\033[0m"
|
|
) >&2
|
|
exit 1
|
|
}
|
|
|
|
###############################################################################
|
|
|
|
CLEANUP_FILES=()
|
|
DO_CLEANUP=1
|
|
cleanup() {
|
|
test "$DO_CLEANUP" = 1 || return 0
|
|
for f in "${CLEANUP_FILES[@]}" ; do
|
|
rm -rf "$f"
|
|
done
|
|
}
|
|
|
|
trap cleanup EXIT
|
|
|
|
###############################################################################
|
|
|
|
tmp_file() {
|
|
cat > "$1"
|
|
CLEANUP_FILES+=( "$1" )
|
|
test -z "$2" || chmod "$2" "$1"
|
|
}
|
|
|
|
gen_file() {
|
|
local PERMS
|
|
[[ $1 =~ bin-* ]] && PERMS=755 || PERMS=644
|
|
sed "s|{{BASEDIR_NM}}|$BASEDIR_NM|g" "$BASEDIR_DATA/$1.in" \
|
|
| tmp_file "$BASEDIR_DATA/data-$1" $PERMS
|
|
}
|
|
|
|
bind_files() {
|
|
VARIABLE_NAME="$1"
|
|
|
|
ARR=()
|
|
H=~
|
|
|
|
ARR+=( -v "$BASEDIR_NM:$BASEDIR_NM" )
|
|
|
|
if [ -e "$BASEDIR_NM/.git/nm-in-container-host" ] ; then
|
|
ARR+=( -v /:/Host )
|
|
fi
|
|
|
|
for i in $(seq 1 ${#SYMLINK_TARGET[@]}) ; do
|
|
j=$((i - 1))
|
|
ARR+=( -v "${SYMLINK_TARGET[$j]}:${SYMLINK_TARGET[$j]}" )
|
|
done
|
|
|
|
for f in ~/.gitconfig* ~/.vim* ; do
|
|
test -e "$f" || continue
|
|
f2="${f#$H/}"
|
|
[[ "$f2" = .viminf* ]] && continue
|
|
[[ "$f2" = *.tmp ]] && continue
|
|
[[ "$f2" = *~ ]] && continue
|
|
f2="/root/$f2"
|
|
ARR+=( -v "$f:$f2" )
|
|
done
|
|
|
|
eval "$VARIABLE_NAME=( \"\${ARR[@]}\" )"
|
|
}
|
|
|
|
create_dockerfile() {
|
|
|
|
local CONTAINERFILE="$1"
|
|
local BASE_IMAGE="$2"
|
|
local GEN_FILES="bin-nm-env-prepare.sh bin-nm-deploy.sh bin-_nm-in-container-setup.sh
|
|
etc-rc.local etc-motd-container etc-bashrc.my etc-bashrc-motd.my nm-90-my.conf
|
|
nm-95-user.conf home-bash_history home-gdbinit home-gdb_history home-behaverc
|
|
systemd-20-nm.override"
|
|
|
|
cp "$BASEDIR_NM/contrib/scripts/NM-log" "$BASEDIR_DATA/data-bin-NM-log"
|
|
CLEANUP_FILES+=( "$BASEDIR_DATA/data-NM-log" )
|
|
|
|
for f in $GEN_FILES; do
|
|
gen_file "$f"
|
|
done
|
|
chmod 755 "$BASEDIR_DATA/data-etc-rc.local"
|
|
|
|
RUN_LN_BASEDIR_NM=
|
|
if [ -n "$BASEDIR_NM" -a "$BASEDIR_NM" != "/NetworkManager" ] ; then
|
|
RUN_LN_BASEDIR_NM="RUN ln -snf \"$BASEDIR_NM\" /NetworkManager"
|
|
fi
|
|
|
|
RUN_LN_SYMLINK_CMDS=""
|
|
for i in $(seq 1 ${#SYMLINK_NAME[@]}) ; do
|
|
j=$((i - 1))
|
|
if [ -d "${SYMLINK_TARGET[$j]}" ] ; then
|
|
RUN_LN_SYMLINK_CMDS="$RUN_LN_SYMLINK_CMDS"$'\n'"RUN ln -snf \"${SYMLINK_TARGET[$j]}\" \"/${SYMLINK_NAME[$j]}\""
|
|
fi
|
|
done
|
|
|
|
cat <<EOF | tmp_file "$CONTAINERFILE"
|
|
FROM $BASE_IMAGE
|
|
|
|
ENTRYPOINT ["/sbin/init"]
|
|
|
|
RUN sed -i 's/^tsflags=.*/tsflags=/' /etc/dnf/dnf.conf
|
|
|
|
RUN dnf install -y \\
|
|
--skip-broken \\
|
|
\\
|
|
/usr/bin/python \\
|
|
/usr/sbin/ausearch \\
|
|
ModemManager-devel \\
|
|
ModemManager-glib-devel \\
|
|
NetworkManager \\
|
|
audit-libs-devel \\
|
|
bash-completion \\
|
|
bind-utils \\
|
|
black \\
|
|
bluez-libs-devel \\
|
|
ccache \\
|
|
clang \\
|
|
clang-tools-extra \\
|
|
cscope \\
|
|
dbus-devel \\
|
|
dbus-x11 \\
|
|
dhclient \\
|
|
dnsmasq \\
|
|
firewalld-filesystem \\
|
|
gcc-c++ \\
|
|
gdb \\
|
|
gettext-devel \\
|
|
git \\
|
|
glib2-doc \\
|
|
glibc-langpack-pl \\
|
|
gnutls-devel \\
|
|
gobject-introspection-devel \\
|
|
gtk-doc \\
|
|
intltool \\
|
|
iproute \\
|
|
iproute-tc \\
|
|
iptables \\
|
|
jansson-devel \\
|
|
libasan \\
|
|
libcurl-devel \\
|
|
libndp-devel \\
|
|
libpsl-devel \\
|
|
libselinux-devel \\
|
|
libtool \\
|
|
libubsan \\
|
|
libuuid-devel \\
|
|
make \\
|
|
meson \\
|
|
mlocate \\
|
|
mobile-broadband-provider-info-devel \\
|
|
newt-devel \\
|
|
nispor \\
|
|
nmstate \\
|
|
nss-devel \\
|
|
polkit-devel \\
|
|
ppp \\
|
|
ppp-devel \\
|
|
procps \\
|
|
python3-behave \\
|
|
python3-black \\
|
|
python3-dbus \\
|
|
python3-devel \\
|
|
python3-gobject \\
|
|
python3-pexpect \\
|
|
python3-pip \\
|
|
python3-pyte \\
|
|
python3-pyyaml \\
|
|
qt-devel \\
|
|
radvd \\
|
|
readline-devel \\
|
|
rp-pppoe \\
|
|
rpm-build \\
|
|
strace \\
|
|
systemd \\
|
|
systemd-devel \\
|
|
tcpdump \\
|
|
teamd-devel \\
|
|
vala \\
|
|
vala-devel \\
|
|
valgrind \\
|
|
vim \\
|
|
which \\
|
|
\\
|
|
'dbus*' \\
|
|
'openvswitch2*' \\
|
|
/usr/bin/pytest \\
|
|
/usr/bin/debuginfo-install \\
|
|
NetworkManager-openvpn \\
|
|
NetworkManager-pptp \\
|
|
NetworkManager-strongswan \\
|
|
NetworkManager-vpnc \\
|
|
NetworkManager-ovs \\
|
|
NetworkManager-wifi \\
|
|
NetworkManager-team \\
|
|
NetworkManager-ppp \\
|
|
cryptsetup \\
|
|
dhcp-client \\
|
|
dhcp-relay \\
|
|
dhcp-server \\
|
|
dnsmasq \\
|
|
dracut-network \\
|
|
ethtool \\
|
|
firewalld \\
|
|
gcc \\
|
|
git \\
|
|
hostapd \\
|
|
iproute-tc \\
|
|
ipsec-tools \\
|
|
iputils \\
|
|
iscsi-initiator-utils \\
|
|
iw \\
|
|
ldns \\
|
|
libreswan \\
|
|
libselinux-utils \\
|
|
libyaml-devel \\
|
|
logrotate \\
|
|
lvm2 \\
|
|
mdadm \\
|
|
net-tools \\
|
|
nfs-utils \\
|
|
nmap-ncat \\
|
|
nss-tools \\
|
|
openvpn \\
|
|
perl-IO-Pty-Easy \\
|
|
perl-IO-Tty \\
|
|
psmisc \\
|
|
python3-dbus \\
|
|
python3-gobject \\
|
|
python3-netaddr \\
|
|
qemu-kvm \\
|
|
radvd \\
|
|
rp-pppoe \\
|
|
scsi-target-utils \\
|
|
tcpdump \\
|
|
tcpreplay \\
|
|
tuned \\
|
|
wireguard-tools \\
|
|
wireshark-cli
|
|
|
|
RUN dnf debuginfo-install --skip-broken NetworkManager \$(ldd /usr/sbin/NetworkManager | sed -n 's/.* => \\(.*\\) (0x[0-9A-Fa-f]*)$/\1/p' | xargs -n1 readlink -f) -y
|
|
|
|
RUN dnf clean all
|
|
|
|
RUN pip3 install --user behave_html_formatter || true
|
|
|
|
RUN mkdir -p /etc/systemd/system/NetworkManager.service.d
|
|
|
|
COPY data-bin-NM-log "/usr/bin/NM-log"
|
|
COPY data-bin-nm-env-prepare.sh "/usr/bin/nm-env-prepare.sh"
|
|
COPY data-bin-nm-deploy.sh "/usr/bin/nm-deploy.sh"
|
|
COPY data-bin-_nm-in-container-setup.sh "/usr/bin/_nm-in-container-setup.sh"
|
|
COPY data-etc-rc.local "/etc/rc.d/rc.local"
|
|
COPY data-etc-motd-container /etc/motd
|
|
COPY data-etc-bashrc.my /etc/bashrc.my
|
|
COPY data-etc-bashrc-motd.my /etc/bashrc-motd.my
|
|
COPY data-nm-90-my.conf /etc/NetworkManager/conf.d/90-my.conf
|
|
COPY data-nm-95-user.conf /etc/NetworkManager/conf.d/95-user.conf
|
|
COPY data-home-bash_history /root/.bash_history
|
|
COPY data-home-gdbinit /root/.gdbinit
|
|
COPY data-home-gdb_history /root/.gdb_history
|
|
COPY data-home-behaverc /root/.behaverc
|
|
COPY data-systemd-20-nm.override /etc/systemd/system/NetworkManager.service.d/20-nm.override
|
|
|
|
RUN systemctl enable NetworkManager
|
|
|
|
# Generate a stable machine id.
|
|
RUN echo "10001000100010001000100010001000" > /etc/machine-id
|
|
|
|
RUN echo -e "# Default from the container image\nnameserver 8.8.8.8" > /etc/resolv.conf
|
|
|
|
# Generate a fixed (version 1) secret key.
|
|
RUN mkdir -p /var/lib/NetworkManager
|
|
RUN chmod 700 /var/lib/NetworkManager
|
|
RUN echo -n "nm-in-container-secret-key" > /var/lib/NetworkManager/secret_key
|
|
RUN chmod 600 /var/lib/NetworkManager/secret_key
|
|
|
|
RUN mkdir -p /etc/systemd/journald.conf.d/ && \
|
|
echo "RateLimitBurst=0" > /etc/systemd/journald.conf.d/no-rate-limit.conf
|
|
|
|
$RUN_LN_BASEDIR_NM
|
|
$RUN_LN_SYMLINK_CMDS
|
|
|
|
RUN rm -rf /etc/NetworkManager/system-connections/*
|
|
|
|
RUN echo -e '\n. /etc/bashrc.my\n' >> /etc/bashrc
|
|
RUN echo -e '\n. /etc/bashrc-motd.my\n' >> /etc/bashrc
|
|
|
|
RUN updatedb
|
|
EOF
|
|
}
|
|
|
|
###############################################################################
|
|
|
|
container_image_exists() {
|
|
podman image exists "$1" || return 1
|
|
}
|
|
|
|
container_exists() {
|
|
podman container exists "$1" || return 1
|
|
}
|
|
|
|
container_is_running() {
|
|
test "$(podman ps --format "{{.ID}} {{.Names}}" | sed -n "s/ $1\$/\0/p")" != "" || return 1
|
|
}
|
|
|
|
###############################################################################
|
|
|
|
do_reset() {
|
|
podman stop "$CONTAINER_NAME_NAME" || :
|
|
podman rm "$CONTAINER_NAME_NAME" || :
|
|
}
|
|
|
|
do_clean() {
|
|
do_reset
|
|
podman rmi "$CONTAINER_NAME_REPOSITORY:$CONTAINER_NAME_TAG" || :
|
|
}
|
|
|
|
do_build() {
|
|
container_image_exists "$CONTAINER_NAME_REPOSITORY:$CONTAINER_NAME_TAG" && return 0
|
|
|
|
CONTAINERFILE="$BASEDIR_DATA/containerfile"
|
|
create_dockerfile "$CONTAINERFILE" "$BASE_IMAGE"
|
|
podman build --squash-all --tag "$CONTAINER_NAME_REPOSITORY:$CONTAINER_NAME_TAG" -f "$CONTAINERFILE"
|
|
}
|
|
|
|
do_run() {
|
|
do_build
|
|
|
|
if container_is_running "$CONTAINER_NAME_NAME" ; then
|
|
return 0
|
|
fi
|
|
|
|
if container_exists "$CONTAINER_NAME_NAME" ; then
|
|
podman start "$CONTAINER_NAME_NAME"
|
|
return 0
|
|
fi
|
|
|
|
bind_files BIND_FILES
|
|
|
|
podman run --privileged \
|
|
--name "$CONTAINER_NAME_NAME" \
|
|
--dns=none \
|
|
--no-hosts \
|
|
-d \
|
|
"${BIND_FILES[@]}" \
|
|
"$CONTAINER_NAME_REPOSITORY:$CONTAINER_NAME_TAG"
|
|
}
|
|
|
|
do_exec() {
|
|
do_run
|
|
|
|
local e
|
|
local EXTRA_ARGS=("$@")
|
|
if [ "${#EXTRA_ARGS[@]}" = 0 ]; then
|
|
EXTRA_ARGS=('bash')
|
|
fi
|
|
|
|
local ENV=()
|
|
for e in "${EXEC_ENV[@]}" ; do
|
|
ENV+=(-e "$e")
|
|
done
|
|
|
|
podman exec "${ENV[@]}" --workdir "$BASEDIR_NM" -it "$CONTAINER_NAME_NAME" "${EXTRA_ARGS[@]}"
|
|
|
|
if [ "$DO_STOP" = 1 ]; then
|
|
do_stop
|
|
fi
|
|
}
|
|
|
|
do_reexec() {
|
|
do_reset
|
|
do_exec "$@"
|
|
}
|
|
|
|
do_journal() {
|
|
EXEC_ENV+=( "SYSTEMD_COLORS=0" )
|
|
do_exec "journalctl" --no-pager "$@"
|
|
}
|
|
|
|
do_stop() {
|
|
container_is_running "$CONTAINER_NAME_NAME" || return 0
|
|
podman stop "$CONTAINER_NAME_NAME"
|
|
}
|
|
|
|
###############################################################################
|
|
|
|
DO_STOP=0
|
|
CMD=exec
|
|
EXTRA_ARGS=()
|
|
for (( i=1 ; i<="$#" ; )) ; do
|
|
c="${@:$i:1}"
|
|
i=$((i+1))
|
|
case "$c" in
|
|
--no-cleanup)
|
|
DO_CLEANUP=0
|
|
;;
|
|
--stop)
|
|
DO_STOP=1
|
|
;;
|
|
j)
|
|
CMD=journal
|
|
;;
|
|
build|run|exec|stop|reset|reexec|clean|journal)
|
|
CMD=$c
|
|
;;
|
|
--)
|
|
EXTRA_ARGS=( "${@:$i}" )
|
|
break
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
if [ "$CMD" = "journal" ]; then
|
|
EXTRA_ARGS=( "${@:$((i-1))}" )
|
|
break;
|
|
else
|
|
usage
|
|
die "invalid argument: $c"
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
|
|
###############################################################################
|
|
|
|
test "$UID" != 0 || die "cannot run as root"
|
|
|
|
if test "$CMD" != exec -a "$CMD" != journal -a "$CMD" != reexec -a "${#EXTRA_ARGS[@]}" != 0 ; then
|
|
die "Extra arguments are only allowed with exec|journal|reexec command"
|
|
fi
|
|
|
|
###############################################################################
|
|
|
|
do_$CMD "${EXTRA_ARGS[@]}"
|