#!/bin/bash
# Copyright 2018- The Pixie Authors.
#
# 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.
#
# SPDX-License-Identifier: Apache-2.0

# This script sets up the basic system and launches the test runner.

set -e

function err {
  retval="${?:-9}"
  /bin/exit_qemu_with_status "${retval}"
}

trap err EXIT
trap err ERR

function mount_cgroupv1() {
  mkdir -p /sys/fs/cgroup
  mount -t tmpfs tmpfs /sys/fs/cgroup
  paths=(
    "blkio"
    "cpu,cpuacct"
    "devices"
    "memory"
    "pids"
    "cpuset"
    "freezer"
    "perf_event"
    "rdma"
  )
  for p in "${paths[@]}"
  do
    mkdir -p "/sys/fs/cgroup/$p"
    mount -t cgroup cgroup -o "$p" "/sys/fs/cgroup/$p"
  done
}

function mount_cgroupv2() {
  mkdir -p /sys/fs/cgroup
  mount -t cgroup2 cgroup2 /sys/fs/cgroup
}

function  mount_cgroup() {
  kernel_major_version="$(uname -r | cut -d'.' -f1)"
  kernel_minor_version="$(uname -r | cut -d'.' -f2)"
  # If the kernel version is below 5.2, then use cgroupv1.
  if [[ "${kernel_major_version}" -le "4" ]] || ([[ "${kernel_major_version}" -eq "5" ]] && [[ "${kernel_minor_version}" -lt "2" ]]); then
    echo "Using cgroup v1"
    mount_cgroupv1
  else
    echo "Using cgroup v2"
    mount_cgroupv2
  fi
}

function mount_system_dirs() {
  mount -t sysfs none /sys
  mount -t debugfs none /sys/kernel/debug
  mount -t bpf none /sys/fs/bpf
  mount -t tracefs none /sys/kernel/tracing
  mount -t tmpfs tmpfs /run

  mkdir -p /dev/shm
  mount -t tmpfs tmpfs /dev/shm

  mkdir -p /dev/pts
  mount -t devpts devpts /dev/pts
}

function mount_test_fs() {
  # Mount the test filesystem.
  mkdir -p /test_fs
  mount -t 9p -o trans=virtio test_fs /test_fs || true
}

function setup_eth0() {
  ip link set dev eth0 up
  ifconfig eth0 10.0.2.15 netmask 255.255.255.0
  route add default gw 10.0.2.2
}

function setup_networking() {
  ip link set dev lo up

  if [[ -f "/etc/hostname" ]]; then
      hostname -F /etc/hostname
  fi

  if [[ ! -f /etc/hosts ]]; then
      cat <<EOF > /etc/hosts
127.0.0.1 localhost

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

EOF
  fi
  setup_eth0
}

function setup_containers() {
  # Remove podman bridge file if it exists.
  rm -f /etc/cni/net.d/87-podman-bridge.conflist


  # Write container setup file for podman.
  cat <<EOF > /etc/containers/containers.conf
[containers]
log_driver = "k8s-file"

[engine]
cgroup_manager = "cgroupfs"
events_logger="file"
runtime="crun"

EOF
}

function link_if_not_exists() {
  # Creates a link if it does not already exist.
  s="$1"
  d="$2"
  if [[ -z "$s" || -z "$d" ]]; then
    echo "src and dest are required arguments"
    exit 1
  fi
  if [[ ! -f "$d" ]]; then
    ln -s "$s" "$d"
  fi
}

# We need proc mounted, otherwise the future mounts commands will fail.
mount -t proc none /proc

# Remount the root filesystem, since it starts out read-only.
mount -o rw,remount /

mount_system_dirs
mount_cgroup
mount_test_fs
setup_networking
setup_containers

link_if_not_exists /usr/sbin/iptables-legacy /usr/bin/iptables
link_if_not_exists /usr/sbin/iptables-legacy /usr/bin/iptables
link_if_not_exists /usr/sbin/ip6tables-legacy /usr/bin/ip6tables
link_if_not_exists /usr/sbin/iptables-legacy-save /usr/bin/iptables-save
link_if_not_exists /usr/sbin/iptables-legacy-restore /usr/bin/iptables-restore
link_if_not_exists /usr/sbin/ip6tables-legacy-save /usr/bin/ip6tables-save
link_if_not_exists /usr/sbin/ip6tables-legacy-restore /usr/bin/ip6tables-restore


cat <<EOF

Boot took $(cut -d' ' -f1 /proc/uptime) seconds

Welcome to PX BPF Runner

EOF

run_sshd="/test_fs/run_sshd.sh"
if [[ -x "${run_sshd}" ]]; then
  exec /bin/bash -c "${run_sshd}"
else
  exec /bin/exit_qemu_with_status 3
fi
