lib.sh 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #!/bin/sh
  2. # Source the main regression test library if present
  3. [ -f "${RT_LIB}" ] && . "${RT_LIB}"
  4. # Temporary directory for tests to use.
  5. AYA_TMPDIR="${RT_PROJECT_ROOT}/_tmp"
  6. # Directory for VM images
  7. AYA_IMGDIR="${RT_PROJECT_ROOT}/_images"
  8. # Cancel Exit Code
  9. RT_CANCEL=253
  10. # Test Architecture
  11. if [ -z "${AYA_TEST_ARCH}" ]; then
  12. AYA_TEST_ARCH="$(uname -m)"
  13. fi
  14. # Test Image
  15. if [ -z "${AYA_TEST_IMAGE}" ]; then
  16. AYA_TEST_IMAGE="fedora35"
  17. fi
  18. case "${AYA_TEST_IMAGE}" in
  19. fedora*) AYA_SSH_USER="fedora";;
  20. centos*) AYA_SSH_USER="centos";;
  21. esac
  22. # compiles the ebpf program by using rust-script to create a temporary
  23. # cargo project in $(pwd)/ebpf. caller must add rm -rf ebpf to the clean_up
  24. # functionAYA_TEST_ARCH
  25. compile_ebpf() {
  26. file=$(basename "$1")
  27. dir=$(dirname "$1")
  28. base=$(echo "${file}" | cut -f1 -d '.')
  29. rm -rf "${dir}/ebpf"
  30. rust-script --pkg-path "${dir}/ebpf" --gen-pkg-only "$1"
  31. artifact=$(sed -n 's/^name = \"\(.*\)\"/\1/p' "${dir}/ebpf/Cargo.toml" | head -n1)
  32. mkdir -p "${dir}/.cargo"
  33. cat > "${dir}/.cargo/config.toml" << EOF
  34. [build]
  35. target = "bpfel-unknown-none"
  36. [unstable]
  37. build-std = ["core"]
  38. EOF
  39. cat >> "${dir}/ebpf/Cargo.toml" << EOF
  40. [workspace]
  41. members = []
  42. EOF
  43. # overwrite the rs file as rust-script adds a main fn
  44. cp "$1" "${dir}/ebpf/${file}"
  45. cargo build -q --manifest-path "${dir}/ebpf/Cargo.toml"
  46. mv "${dir}/ebpf/target/bpfel-unknown-none/debug/${artifact}" "${dir}/${base}.o"
  47. rm -rf "${dir}/.cargo"
  48. rm -rf "${dir}/ebpf"
  49. }
  50. # compile a C BPF file
  51. compile_c_ebpf() {
  52. file=$(basename "$1")
  53. dir=$(dirname "$1")
  54. base=$(echo "${file}" | cut -f1 -d '.')
  55. rust-script "${RT_PROJECT_ROOT}/_lib/compile-ebpf.ers" "${1}" "${dir}/${base}.o"
  56. rm -rf "${dir}/include"
  57. }
  58. # compiles the userspace program by using rust-script to create a temporary
  59. # cargo project in $(pwd)/user. caller must add rm -rf ebpf to the clean_up
  60. # function. this is required since the binary produced has to be run with
  61. # sudo to load an eBPF program
  62. compile_user() {
  63. file=$(basename "$1")
  64. dir=$(dirname "$1")
  65. base=$(echo "${file}" | cut -f1 -d '.')
  66. rm -rf "${dir}/user"
  67. rust-script --pkg-path "${dir}/user" --gen-pkg-only "$1"
  68. artifact=$(sed -n 's/^name = \"\(.*\)\"/\1/p' "${dir}/user/Cargo.toml" | head -n1)
  69. cat >> "${dir}/user/Cargo.toml" << EOF
  70. [workspace]
  71. members = []
  72. EOF
  73. cargo build -q --release --manifest-path "${dir}/user/Cargo.toml" --target=x86_64-unknown-linux-musl
  74. mv "${dir}/user/target/x86_64-unknown-linux-musl/release/${artifact}" "${dir}/${base}"
  75. rm -rf "${dir}/user"
  76. }
  77. download_images() {
  78. mkdir -p "${AYA_IMGDIR}"
  79. case $1 in
  80. fedora35)
  81. if [ ! -f "${AYA_IMGDIR}/fedora35.${AYA_TEST_ARCH}.qcow2" ]; then
  82. IMAGE="Fedora-Cloud-Base-35-1.2.${AYA_TEST_ARCH}.qcow2"
  83. IMAGE_URL="https://download.fedoraproject.org/pub/fedora/linux/releases/35/Cloud/${AYA_TEST_ARCH}/images"
  84. echo "Downloading: ${IMAGE}, this may take a while..."
  85. curl -o "${AYA_IMGDIR}/fedora35.${AYA_TEST_ARCH}.qcow2" -sSL "${IMAGE_URL}/${IMAGE}"
  86. fi
  87. ;;
  88. centos8)
  89. if [ ! -f "${AYA_IMGDIR}/centos8.${AYA_TEST_ARCH}.qcow2" ]; then
  90. IMAGE="CentOS-8-GenericCloud-8.4.2105-20210603.0.${AYA_TEST_ARCH}.qcow2"
  91. IMAGE_URL="https://cloud.centos.org/centos/8/${AYA_TEST_ARCH}/images"
  92. echo "Downloading: ${IMAGE}, this may take a while..."
  93. curl -o "${AYA_IMGDIR}/centos8.${AYA_TEST_ARCH}.qcow2" -sSL "${IMAGE_URL}/${IMAGE}"
  94. fi
  95. ;;
  96. *)
  97. echo "$1 is not a recognized image name"
  98. return 1
  99. ;;
  100. esac
  101. }
  102. start_vm() {
  103. download_images "${AYA_TEST_IMAGE}"
  104. # prepare config
  105. cat > "${AYA_TMPDIR}/metadata.yaml" <<EOF
  106. instance-id: iid-local01
  107. local-hostname: test
  108. EOF
  109. if [ ! -f "${AYA_TMPDIR}/test_rsa" ]; then
  110. ssh-keygen -t rsa -b 4096 -f "${AYA_TMPDIR}/test_rsa" -N "" -C "" -q
  111. pub_key=$(cat "${AYA_TMPDIR}/test_rsa.pub")
  112. cat > "${AYA_TMPDIR}/user-data.yaml" <<EOF
  113. #cloud-config
  114. ssh_authorized_keys:
  115. - ${pub_key}
  116. EOF
  117. fi
  118. if [ ! -f "${AYA_TMPDIR}/ssh_config" ]; then
  119. cat > "${AYA_TMPDIR}/ssh_config" <<EOF
  120. StrictHostKeyChecking=no
  121. UserKnownHostsFile=/dev/null
  122. GlobalKnownHostsFile=/dev/null
  123. EOF
  124. fi
  125. cloud-localds "${AYA_TMPDIR}/seed.img" "${AYA_TMPDIR}/user-data.yaml" "${AYA_TMPDIR}/metadata.yaml"
  126. case "${AYA_TEST_ARCH}" in
  127. x86_64)
  128. QEMU=qemu-system-x86_64
  129. machine="q35"
  130. cpu="qemu64"
  131. if [ "$(uname -m)" = "${AYA_TEST_ARCH}" ]; then
  132. if [ -c /dev/kvm ]; then
  133. machine="${machine},accel=kvm"
  134. cpu="host"
  135. elif [ "$(uname -s)" = "Darwin" ]; then
  136. machine="${machine},accel=hvf"
  137. cpu="host"
  138. fi
  139. fi
  140. ;;
  141. aarch64)
  142. QEMU=qemu-system-aarch64
  143. machine="virt"
  144. cpu="cortex-a57"
  145. if [ "$(uname -m)" = "${AYA_TEST_ARCH}" ]; then
  146. if [ -c /dev/kvm ]; then
  147. machine="${machine},accel=kvm"
  148. cpu="host"
  149. elif [ "$(uname -s)" = "Darwin" ]; then
  150. machine="${machine},accel=hvf"
  151. cpu="host"
  152. fi
  153. fi
  154. ;;
  155. *)
  156. echo "${AYA_TEST_ARCH} is not supported"
  157. return 1
  158. ;;
  159. esac
  160. qemu-img create -F qcow2 -f qcow2 -o backing_file="${AYA_IMGDIR}/${AYA_TEST_IMAGE}.${AYA_TEST_ARCH}.qcow2" "${AYA_TMPDIR}/vm.qcow2" || return 1
  161. $QEMU \
  162. -machine "${machine}" \
  163. -cpu "${cpu}" \
  164. -m 2G \
  165. -display none \
  166. -monitor none \
  167. -daemonize \
  168. -pidfile "${AYA_TMPDIR}/vm.pid" \
  169. -device virtio-net-pci,netdev=net0 \
  170. -netdev user,id=net0,hostfwd=tcp::2222-:22 \
  171. -drive if=virtio,format=qcow2,file="${AYA_TMPDIR}/vm.qcow2" \
  172. -drive if=virtio,format=raw,file="${AYA_TMPDIR}/seed.img" || return 1
  173. trap cleanup_vm EXIT
  174. echo "Waiting for SSH on port 2222..."
  175. retry=0
  176. max_retries=300
  177. while ! ssh -q -F "${AYA_TMPDIR}/ssh_config" -o ConnectTimeout=1 -i "${AYA_TMPDIR}/test_rsa" ${AYA_SSH_USER}@localhost -p 2222 echo "Hello VM"; do
  178. retry=$((retry+1))
  179. if [ ${retry} -gt ${max_retries} ]; then
  180. echo "Unable to connect to VM"
  181. return 1
  182. fi
  183. sleep 1
  184. done
  185. echo "VM launched, installing dependencies"
  186. exec_vm sudo dnf install -qy bpftool
  187. }
  188. scp_vm() {
  189. local=$1
  190. scp -q -F "${AYA_TMPDIR}/ssh_config" \
  191. -i "${AYA_TMPDIR}/test_rsa" \
  192. -P 2222 "${local}" \
  193. "${AYA_SSH_USER}@localhost:${local}"
  194. }
  195. exec_vm() {
  196. ssh -q -F "${AYA_TMPDIR}/ssh_config" \
  197. -i "${AYA_TMPDIR}/test_rsa" \
  198. -p 2222 \
  199. ${AYA_SSH_USER}@localhost \
  200. "$@"
  201. }
  202. stop_vm() {
  203. if [ -f "${AYA_TMPDIR}/vm.pid" ]; then
  204. echo "Stopping VM forcefully"
  205. kill -9 "$(cat "${AYA_TMPDIR}/vm.pid")"
  206. rm "${AYA_TMPDIR}/vm.pid"
  207. fi
  208. rm -f "${AYA_TMPDIR}/vm.qcow2"
  209. }
  210. cleanup_vm() {
  211. if [ "$?" != "0" ]; then
  212. stop_vm
  213. fi
  214. }
  215. # Check that host machine meets minimum kernel requirement
  216. # Must be in format {major}.{minor}
  217. min_kernel_version() {
  218. target_major=$(echo "$1" | cut -d '.' -f1)
  219. target_minor=$(echo "$1" | cut -d '.' -f2)
  220. vm_kernel=$(exec_vm uname -r)
  221. vm_major=$(echo "${vm_kernel}" | cut -d '.' -f1)
  222. vm_minor=$(echo "${vm_kernel}" | cut -d '.' -f2)
  223. if [ "${vm_major}" -lt "${target_major}" ] || [ "${vm_minor}" -lt "${target_minor}" ]; then
  224. echo "Test not supported on kernel ${vm_major}.${vm_minor}"
  225. return ${RT_CANCEL}
  226. fi
  227. return 0
  228. }