diff --git a/deploy_scripts/Dockerfiles/Dockerfile_amd b/deploy_scripts/Dockerfiles/Dockerfile_amd new file mode 100644 index 0000000000000000000000000000000000000000..039fd2d2a29eeb5f9ee44ed49404e2c68aaac74c --- /dev/null +++ b/deploy_scripts/Dockerfiles/Dockerfile_amd @@ -0,0 +1,21 @@ +# 本文件将基于kbox基础云手机镜像和kbox二进制制作适用于amd gpu 云手机镜像 +# 本文件前提是保证已有kbox基础云手机镜像(如kbox:latest) +# 在kbox基础云手机镜像的基础上将kbox二进制放入kbox基础云手机镜像中 +# 使用docker命令制作kbox云手机镜像,方便用户使用 + +# ARG是定义参数名称 +# FROM是指定kbox基础云手机镜像 +# MAINTAINER是作者名 +ARG KBOX_IMAGE +FROM ${KBOX_IMAGE} +MAINTAINER root + +COPY ./imageFile/system /imageFile/system + +# 注意: +# 因为每运行RUN一次就会创建一层镜像,容易产生非常臃肿、非常多层的镜像 +# 所以将视频流云手机相关的所有二进制整合在一起,保证只运行一次RUN +RUN chmod -R 755 imageFile \ + && chown -R root:root imageFile \ + && cp -pR imageFile/system/* /system/ \ + && rm -rf imageFile diff --git a/deploy_scripts/Dockerfiles/Dockerfile_awm b/deploy_scripts/Dockerfiles/Dockerfile_awm new file mode 100644 index 0000000000000000000000000000000000000000..ec8a925b5b7fef1c6fbedac87f6f5f7e4724be3d --- /dev/null +++ b/deploy_scripts/Dockerfiles/Dockerfile_awm @@ -0,0 +1,36 @@ +# 本文件将基于kbox基础云手机镜像和awmgpu相关的二进制制作awmgpu云手机镜像 +# 本文件前提是保证已有kbox基础云手机镜像(如kbox:latest) +# 在kbox基础云手机镜像的基础上将awmgpu相关的二进制放入kbox基础云手机镜像中 +# 使用docker命令制作视频流云手机镜像(如kbox:latest_awm),方便用户使用 + +# ARG是定义参数名称 +# FROM是指定kbox基础云手机镜像 +# MAINTAINER是作者名 +ARG KBOX_IMAGE +FROM ${KBOX_IMAGE} +MAINTAINER root + +COPY ./imageFile/system /imageFile/system + +# 注意: +# 因为每运行RUN一次就会创建一层镜像,容易产生非常臃肿、非常多层的镜像 +# 所以将视频流云手机相关的所有二进制整合在一起,保证只运行一次RUN +RUN chmod -R 755 imageFile \ + && chown -R root:root imageFile \ + && cp -pR imageFile/system/* /system/ \ + && rm -rf imageFile \ + && sed -i 's/^ro.hardware.gralloc=.*/ro.hardware.gralloc=awmgpu/g' /system/build.prop \ + && sed -i 's/^ro.hardware.hwcomposer=.*/ro.hardware.hwcomposer=awmgpu/g' /system/build.prop \ + && sed -i 's/^ro.hardware.egl=.*/ro.hardware.egl=powervr/g' /system/build.prop \ + && sed -i 's/^ro.hardware.vulkan=.*/ro.hardware.vulkan=powervr/g' /system/build.prop \ + && sed -i 's/^ro.product.platform=.*/ro.product.platform=powervr/g' /system/build.prop \ + && sed -i 's/^ro.vmi.hardware.gpu=.*/ro.vmi.hardware.gpu=2/g' /system/build.prop \ + && sed -i 's/^ro.vmi.hardware.vpu=.*/ro.vmi.hardware.vpu=0/g' /system/build.prop \ + && sed -i 's/^ro.hardware.gralloc=.*/ro.hardware.gralloc=awmgpu/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.hwcomposer=.*/ro.hardware.hwcomposer=awmgpu/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.egl=.*/ro.hardware.egl=powervr/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.vulkan=.*/ro.hardware.vulkan=powervr/g' /system/vendor/build.prop \ + && sed -i 's/^ro.product.platform=.*/ro.product.platform=powervr/g' /system/vendor/build.prop \ + && sed -i 's/^ro.vmi.hardware.gpu=.*/ro.vmi.hardware.gpu=2/g' /system/vendor/build.prop \ + && sed -i 's/^ro.vmi.hardware.vpu=.*/ro.vmi.hardware.vpu=0/g' /system/vendor/build.prop + diff --git a/deploy_scripts/Dockerfiles/Dockerfile_va b/deploy_scripts/Dockerfiles/Dockerfile_va new file mode 100644 index 0000000000000000000000000000000000000000..3792388a56c2a97802043cfd0dad3d59d3b00389 --- /dev/null +++ b/deploy_scripts/Dockerfiles/Dockerfile_va @@ -0,0 +1,45 @@ +# 本文件将基于kbox基础云手机镜像和va gpu相关的二进制制作va gpu云手机镜像 +# 本文件前提是保证已有kbox基础云手机镜像(如kbox:latest) +# 在kbox基础云手机镜像的基础上将va gpu相关的二进制放入kbox基础云手机镜像中 +# 使用docker命令制作kbox云手机镜像(如kbox:latest_va),方便用户使用 + +# ARG是定义参数名称 +# FROM是指定kbox基础云手机镜像 +# MAINTAINER是作者名 +ARG KBOX_IMAGE +FROM ${KBOX_IMAGE} +MAINTAINER root + +COPY ./imageFile/system /imageFile/system + +# 注意: +# 因为每运行RUN一次就会创建一层镜像,容易产生非常臃肿、非常多层的镜像 +# 所以将视频流云手机相关的所有二进制整合在一起,保证只运行一次RUN +RUN chmod -R 755 imageFile \ + && chown -R root:root imageFile \ + && cp -pR imageFile/system/* /system/ \ + && rm -rf imageFile \ + && sed -i 's/^ro.hardware.gralloc=.*/ro.hardware.gralloc=sgpu100/g' /system/build.prop \ + && sed -i 's/^ro.hardware.hwcomposer=.*/ro.hardware.hwcomposer=sgpu100/g' /system/build.prop \ + && sed -i 's/^ro.hardware.egl=.*/ro.hardware.egl=va/g' /system/build.prop \ + && sed -i 's/^ro.hardware.vulkan=.*/ro.hardware.vulkan=va/g' /system/build.prop \ + && sed -i 's/^ro.product.platform=.*/ro.product.platform=va/g' /system/build.prop \ + && sed -i 's/^ro.vmi.hardware.gpu=.*/ro.vmi.hardware.gpu=257/g' /system/build.prop \ + && sed -i 's/^ro.vmi.hardware.vpu=.*/ro.vmi.hardware.vpu=0/g' /system/build.prop \ + && sed -i 's/^ro.hardware.gralloc=.*/ro.hardware.gralloc=sgpu100/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.hwcomposer=.*/ro.hardware.hwcomposer=sgpu100/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.egl=.*/ro.hardware.egl=va/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.vulkan=.*/ro.hardware.vulkan=va/g' /system/vendor/build.prop \ + && sed -i 's/^ro.product.platform=.*/ro.product.platform=va/g' /system/vendor/build.prop \ + && sed -i 's/^ro.vmi.hardware.gpu=.*/ro.vmi.hardware.gpu=257/g' /system/vendor/build.prop \ + && sed -i 's/^ro.vmi.hardware.vpu=.*/ro.vmi.hardware.vpu=0/g' /system/vendor/build.prop \ + && sed -i '$aro.va.gpu.init=1' /system/vendor/build.prop \ + && sed -i '$adisplayServer.maxInterval=-1' /system/vendor/build.prop \ + && sed -i '/on init/a \ export VASTSTREAM_PIPELINE true' init.kbox.rc \ + && sed -i '/on init/a \ export VASTSTREAM_HOME \/vendor\/lib64\/vame\/' init.kbox.rc \ + && sed -i '/on init/a \ export VACM_LOG_CFG \/vendor\/etc\/' init.kbox.rc \ + && sed -i '/on init/a \ export LIBVASTVA_DRIVERS_PATH \/vendor\/lib64\/' init.kbox.rc \ + && sed -i '/on init/a \ export LIBVASTVA_DRIVER_NAME va' init.kbox.rc \ + && sed -i '/on init/a \ export VACC_RT_DDR_SHARE_MIN_SIZE 4' init.kbox.rc \ + && sed -i '/on init/a \ export VACC_RT_DDR_SHARE_POOL_MAX 0' init.kbox.rc \ + && sed -i '/mount debugfs/a \ exec - root -- /system/vendor/bin/gpu_config.sh' init.kbox.rc diff --git a/deploy_scripts/Dockerfiles/Dockerfile_va_aosp15 b/deploy_scripts/Dockerfiles/Dockerfile_va_aosp15 new file mode 100644 index 0000000000000000000000000000000000000000..f9fc664d2bf919d2b6f9aaa5cc7534838c0216e7 --- /dev/null +++ b/deploy_scripts/Dockerfiles/Dockerfile_va_aosp15 @@ -0,0 +1,51 @@ +# 本文件将基于kbox基础云手机镜像和va gpu相关的二进制制作va gpu云手机镜像 +# 本文件前提是保证已有kbox基础云手机镜像(如kbox:latest) +# 在kbox基础云手机镜像的基础上将va gpu相关的二进制放入kbox基础云手机镜像中 +# 使用docker命令制作kbox云手机镜像(如kbox:latest_va),方便用户使用 + +# ARG是定义参数名称 +# FROM是指定kbox基础云手机镜像 +# MAINTAINER是作者名 +ARG KBOX_IMAGE +FROM ${KBOX_IMAGE} +MAINTAINER root + +COPY ./imageFile/system /imageFile/system + +# 注意: +# 因为每运行RUN一次就会创建一层镜像,容易产生非常臃肿、非常多层的镜像 +# 所以将视频流云手机相关的所有二进制整合在一起,保证只运行一次RUN +RUN cp /system/lib64/liblzma.so /system/vendor/lib64/ \ + && cp /system/lib64/libutilscallstack.so /system/vendor/lib64/ \ + && cp /system/lib64/libunwindstack.so /system/vendor/lib64/ \ + && cp /system/lib/liblzma.so /system/vendor/lib/ \ + && cp /system/lib/libutilscallstack.so /system/vendor/lib/ \ + && cp /system/lib/libunwindstack.so /system/vendor/lib/ \ + && chmod -R 755 imageFile \ + && chown -R root:root imageFile \ + && cp -pR imageFile/system/* /system/ \ + && rm -rf imageFile \ + && sed -i '$aro.hardware.gralloc=sgpu100' /system/build.prop \ + && sed -i '$aro.hardware.hwcomposer=sgpu100' /system/build.prop \ + && sed -i '$aro.hardware.egl=va' /system/build.prop \ + && sed -i '$aro.hardware.vulkan=va' /system/build.prop \ + && sed -i '$aro.product.platform=va' /system/build.prop \ + && sed -i '$aro.vmi.hardware.gpu=257' /system/build.prop \ + && sed -i '$aro.vmi.hardware.vpu=0' /system/build.prop \ + && sed -i '$aro.hardware.gralloc=sgpu100' /system/vendor/build.prop \ + && sed -i '$aro.hardware.hwcomposer=sgpu100' /system/vendor/build.prop \ + && sed -i '$aro.hardware.egl=va' /system/vendor/build.prop \ + && sed -i '$aro.hardware.vulkan=va' /system/vendor/build.prop \ + && sed -i '$aro.product.platform=va' /system/vendor/build.prop \ + && sed -i '$aro.vmi.hardware.gpu=257' /system/vendor/build.prop \ + && sed -i '$aro.vmi.hardware.vpu=0' /system/vendor/build.prop \ + && sed -i '$aro.va.gpu.init=1' /system/vendor/build.prop \ + && sed -i '$adisplayServer.maxInterval=-1' /system/vendor/build.prop \ + && sed -i '/on init/a \ export VASTSTREAM_PIPELINE true' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export VASTSTREAM_HOME \/vendor\/lib64\/vame\/' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export VACM_LOG_CFG \/vendor\/etc\/' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export LIBVASTVA_DRIVERS_PATH \/vendor\/lib64\/' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export LIBVASTVA_DRIVER_NAME va' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export VACC_RT_DDR_SHARE_MIN_SIZE 4' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export VACC_RT_DDR_SHARE_POOL_MAX 0' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/mount debugfs/a \ exec - root -- /system/vendor/bin/gpu_config.sh' /system/vendor/etc/init/init.kbox.rc diff --git a/deploy_scripts/android_kbox_aosp15.sh b/deploy_scripts/android_kbox_aosp15.sh new file mode 100644 index 0000000000000000000000000000000000000000..19e3a149fd89037db72850ff20a489c1f1c95602 --- /dev/null +++ b/deploy_scripts/android_kbox_aosp15.sh @@ -0,0 +1,546 @@ +#!/bin/bash +# Copyright Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. + +#=============================================================================== +# Global Variable +#=============================================================================== +XD_GPU_ID="1fe0:1010" +VA_SGPU100_ID=":0200" + +#=============================================================================== +# Functions +#=============================================================================== +function check_environment() { + # root权限执行此脚本 + if [ "${UID}" -ne 0 ]; then + echo "请使用root权限执行" + exit 1 + fi + + # 支持非当前目录执行 + CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + echo "Current Path:$CURRENT_DIR" + cd ${CURRENT_DIR} + + # 检查是否存在配置文件,不存在配置文件,直接退出 + local KBOX_CFG=$CURRENT_DIR/kbox_config.cfg + if [ -f $KBOX_CFG ] + then + source $KBOX_CFG + echo "kbox_config.cfg exists, loaded" + else + echo "kbox_config.cfg not found" + exit 1 + fi + + check_devices +} + +function check_devices() { + # 确定kernel版本 + local KERNEL_VERSION=$(uname -r) + + # 检查ashmem device + if [ -z $(ls /dev | grep "ashmem") ]; then + echo "can not find ashmem device" + exit 1 + fi + + chmod 600 /dev/ashmem + chmod 600 /dev/dri/* + chmod 600 /dev/input + + if [ -n "$(lspci -n | grep ${XD_GPU_ID})" ]; then + chmod 666 /dev/ion* + chmod 666 /dev/pvr_sync + fi +} + +function check_paras() { + set +e + + if [ $# -eq 0 ]; then + echo "command must be \"start\", \"delete\" or \"restart\" " + exit 1 + fi + + if [ $1 == "start" ]; then + if [ $# -gt 4 ]; then + echo "the number of parameters exceeds 4!" + echo "Usage: " + echo "./android_kbox.sh start " + echo "./android_kbox.sh start " + exit 1; + fi + + local IMAGE_ID=$2 + if [[ "${IMAGE_ID}" =~ ":" ]]; then + local IMAGE_RE=$(echo ${IMAGE_ID} | cut -d ':' -f1) + tag=$(echo ${IMAGE_ID} | cut -d ':' -f2) + docker images | awk '{print $1" "$2}' | grep -w "${IMAGE_RE}" | grep -w "${tag}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "no image ${IMAGE_ID}" + exit 1 + fi + else + docker images | awk '{print $3}' | grep -w "${IMAGE_ID}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "no image ${IMAGE_ID}" + exit 1 + fi + fi + + if [ -n "`echo "$3$4" | sed 's/[0-9]//g'`" ]; then + echo "The third and fourth parameters must be numbers." + exit 1 + fi + + local MIN=$3 MAX=$4 + if [ -z "$4" ]; then + MAX=$3 + fi + + if [ $MIN -gt $MAX ]; then + echo "start_num must be less than or equal to end_num" + exit 1 + fi + elif [ $1 == "delete" ]; then + if [ $# -gt 3 ]; then + echo "the number of parameters exceeds 3!" + echo "Usage: " + echo "./android_kbox.sh delete " + echo "./android_kbox.sh delete " + exit 1 + fi + + if [ -n "`echo "$2$3" | sed 's/[0-9]//g'`" ]; then + echo "The second and third parameters must be numbers." + exit 1 + fi + + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + + if [ $MIN -gt $MAX ]; then + echo "start_num must be less than or equal to end_num" + exit 1 + fi + elif [ $1 == "restart" ]; then + if [ $# -gt 3 ]; then + echo "the number of parameters exceeds 3!" + echo "Usage: " + echo "./android_kbox.sh restart " + echo "./android_kbox.sh restart " + exit 1 + fi + + if [ -n "`echo "$2$3" | sed 's/[0-9]//g'`" ]; then + echo "The second and third paramelters must be numbers." + exit 1 + fi + + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + + if [ $MIN -gt $MAX ]; then + echo "start_num must be less than or equal to end_num" + exit 1 + fi + else + echo "command must be \"start\", \"delete\" or \"restart\" " + fi +} + +function get_closest_numas() { + local NUM_OF_NUMA=$(lscpu | grep "NUMA node(s)" | awk '{print $3}') + + local CPU_LIST_ARRAY= + for ((NUMA=0; NUMA<${NUM_OF_NUMA}; NUMA++)) + do + CPU_LIST_ARRAY[$NUMA]=$(cat /sys/devices/system/node/node${NUMA}/cpulist |sed "s/-/ /") + done + + local CPU_LIST= + for CPU in $@ + do + for ((NUMA=0; NUMA<${NUM_OF_NUMA}; NUMA++)) + do + # 将带空格的文本转换成array,其中第一个元素是最小值,第二个元素是最大值 + CPU_LIST=(${CPU_LIST_ARRAY[$NUMA]}) + if (( ${CPU} >= ${CPU_LIST[0]} )) && (( ${CPU} <= ${CPU_LIST[1]} )) + then + echo $NUMA + fi + done + done +} + +function wait_container_ready() { + local KBOX_NAME=$1 + local starttime=$(date +'%Y-%m-%d %H:%M:%S') + local start_seconds=$(date --date="${starttime}" +%s) + local res=0 + local has_restart=0 + if [ $? -eq 0 ]; then + count_time=0 + set +e + while true; do + local cmd="docker exec -i $1 getprop sys.boot_completed | grep 1 &" + local result=$(bash $CURRENT_DIR/base_box_aosp15.sh wait_async_cmd "${cmd}" 2> /dev/null) + if [ "${result}" == "1" ]; then + bash $CURRENT_DIR/base_box_aosp15.sh chk_key_process ${CONTAINER_NAME} + [ ${?} -ne 0 ] && has_restart=1 && bash $CURRENT_DIR/base_box_aosp15.sh restart "${CONTAINER_NAME}" "$MOUNT_DIR" 2 + [ ${?} -eq 1 ] && [ $has_restart -eq 1 ] && echo "${KBOX_NAME} started failed at $(date +'%Y-%m-%d %H:%M:%S')!" && res=1 && break + + echo "${KBOX_NAME} started successfully at $(date +'%Y-%m-%d %H:%M:%S')!" + break + elif [ "${result}" == "-1" ]; then + echo "${KBOX_NAME} wait_async_cmd timeout, exit and continue!" + fi + # 200秒未成功启动超时跳过 + if [ ${count_time} -gt 200 ]; then + echo -e "\033[1;31mStart check timed out,${KBOX_NAME} unable to start\033[0m" + echo -e "\033[1;31m${KBOX_NAME} started failed\033[0m" + break + fi + sleep 1 + count_time=$((count_time + 1)) + done + else + echo "${KBOX_NAME} started failed" + fi + local endtime=$(date +'%Y-%m-%d %H:%M:%S') + local end_seconds=$(date --date="${endtime}" +%s) + echo "time: "$((end_seconds - start_seconds))"s" + return $res +} + +function disable_ipv6_icmp() { + # 更改容器内部accept_redirects参数配置,禁止ipv6的icmp重定向功能 + KBOX_NAME=$1 + temp=$(mktemp) + echo 0 > $temp + pid=$(docker inspect ${KBOX_NAME} | grep Pid | awk -F, '{print $1}' | sed -n '1p' | awk '{print $2}') + nsenter -n -t ${pid} cp $temp /proc/sys/net/ipv6/conf/all/accept_redirects + rm $temp +} + +function check_encode_card() +{ + # 检查nvme指令 + cmd="nvme --help" + $cmd >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "nvme command unavailable, cannot auto detect vpu" + return 0 + fi + + cmd="nvme list" + output=$($cmd) + if echo "$output" | grep -q "QuadraT2A"; then + echo "set encode card to QuadraT2A" + HARD_DECODE_TYPE=1 + elif echo "$output" | grep -q "T432"; then + echo "set encode card to T432" + HARD_DECODE_TYPE=0 + else + echo "encode card unchange" + fi +} + +function enable_hard_decoder() { + local TAG_NUMBER=$1 + local container_name=kbox_$TAG_NUMBER + # Exited转态时需先重启容器才能拷贝文件 + local MOUNT_DIR=${KBOX_MOUNT_MAP[$TAG_NUMBER - 1]} + local status=$(docker ps -a| grep -w $container_name) + if [[ "$status" =~ "Exited" ]]; then + echo "kbox_$TAG_NUMBER is exited!" + if [ -z ${MOUNT_DIR} ]; then + MOUNT_DIR="/root/mount" + fi + mount ${MOUNT_DIR}/img/${container_name}.img ${MOUNT_DIR}/data/${container_name} >/dev/null + docker start ${container_name} + sleep 2 + fi + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + # VA GPU 硬解逻辑到base_box中处理,兼容视频流 + return; + fi + # 从硬解使能软解 + if [ $ENABLE_HARD_DECODE -ne 1 ];then + docker cp ${container_name}:/system/vendor/etc/media_codecs.xml . + sed -i 's/media_codecs_kbox_video.xml/media_codecs_google_video.xml/g' media_codecs.xml + docker cp ./media_codecs.xml ${container_name}:/system/vendor/etc/ + docker exec -itd ${container_name} chmod 644 /system/vendor/etc/media_codecs.xml + return + fi + # 使能硬解 + docker cp ${container_name}:/system/vendor/etc/media_codecs.xml . + sed -i 's/media_codecs_google_video.xml/media_codecs_kbox_video.xml/g' media_codecs.xml + docker cp ./media_codecs.xml ${container_name}:/system/vendor/etc/ + docker exec -itd ${container_name} chmod 644 /system/vendor/etc/media_codecs.xml + echo "enable hard decoder done" +} + +function enable_netint() { + # 不需要使能硬解设备 + if [ $ENABLE_HARD_DECODE -ne 1 ];then + return + fi + + # VA GPU 无此步骤,直接退出 + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + return; + fi + + container_name=$1 + check_encode_card + # T432初始化执行方式不变;Quadra采用ni_rsrc_mon自启动,生命周期由编码卡厂家管理,此处仅打印返回值 + if [ $HARD_DECODE_TYPE -eq 0 ];then + docker exec -itd ${container_name} /system/bin/ni_rsrc_mon_logan + sleep 3 + docker exec -itd ${container_name} chmod 666 /dev/nvm*n* + docker exec -itd ${container_name} chmod 777 -R /dev/shm_netint + [ ${?} != 0 ] && echo "Failed to enable netint device" && return + echo "enable netint device success" + elif [ $HARD_DECODE_TYPE -eq 1 ];then + local container_name=$1 + local ni_init_success=$(docker exec -itd ${container_name} getprop ni_rsrc_init_completed) + if [ "${ni_init_success}" == "yes" ]; then + echo "Failed to enable netint device" + else + echo "enable netint device success" + fi + else + return; + fi +} + +function netint_run_option() { + container_id=$1 + local opt="" + local encs_string=${KBOX_DEC_MAP[$container_id - 1]} + local encs="" + local encs_dev=() + IFS=',' read -r -a encs_dev <<< $encs_string + for i in ${encs_dev[*]}; do + encs+=" --device=${i}:${i}:rwm" + done + opt+=$encs + + echo "$opt" +} + +function start_box_by_id() { + + # 镜像名 + local IMAGE_NAME=$2 + + # 容器编号 + local TAG_NUMBER=$3 + + # 没有GPU不启动容器 + local GPUS_INFO=($(lspci -D | grep "VGA compatible controller: Advanced Micro Devices" | awk '{print $1}')) + # 芯动/VA GPU卡无法通过以上方式识别 + GPUS_INFO+=$(lspci -n | grep ${XD_GPU_ID} | awk '{print $3}') + GPUS_INFO+=$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}') + if [ ${#GPUS_INFO[@]} -eq 0 ]; then + echo "No GPU exists on the host" + exit 1 + fi + + # 容器名 + local CONTAINER_NAME="kbox_$TAG_NUMBER" + + # 存储大小 + local STORAGE_SIZE_GB=16 + + # 运行内存 + local RAM_SIZE_MB + if [ -n "$(lspci -D | grep "VGA compatible controller: Advanced Micro Devices" | grep "73a3")" ] || \ + [ -n "$(lspci -D | grep "VGA compatible controller: Advanced Micro Devices" | grep "Radeon PRO W6800")" ] || \ + [ -n "$(lspci -n | grep ${XD_GPU_ID})" ] || \ + [ -n "$(lspci -n | grep ${VA_SGPU100_ID})" ]; then + RAM_SIZE_MB=6144 + else + RAM_SIZE_MB=4096 + fi + + # CPUS + local CPUS + local CPUS_STRING=${KBOX_CPUSET_MAP[TAG_NUMBER - 1]} + IFS=' ' read -r -a CPUS <<< $CPUS_STRING + + # GPU + local GPUS_RENDER + if [ -n "$(lspci -n | grep ${XD_GPU_ID})" ]; then + # GPU, XD一个GPU对应四个render + local xd_gpus=($(lspci -D | grep "3D controller" | awk '{print $1}')) + if [ ${#xd_gpus[@]} -eq 2 ]; then + GPUS_RENDER=${KBOX_XD_GPU_MAP_8RENDERS[TAG_NUMBER - 1]} + elif [ ${#xd_gpus[@]} -eq 4 ]; then + GPUS_RENDER=${KBOX_XD_GPU_MAP_16RENDERS[TAG_NUMBER - 1]} + elif [ ${#xd_gpus[@]} -eq 6 ]; then + GPUS_RENDER=${KBOX_XD_GPU_MAP_24RENDERS[TAG_NUMBER - 1]} + else + GPUS_RENDER=${KBOX_XD_GPU_MAP_4RENDERS[TAG_NUMBER - 1]} + fi + elif [ -n "$(lspci -n | grep ${VA_SGPU100_ID})" ]; then + GPUS_RENDER=${KBOX_VA_GPU_MAP[TAG_NUMBER - 1]} + else + GPUS_RENDER=${KBOX_GPU_MAP[TAG_NUMBER - 1]} + fi + + # Data mount dir + local MOUNT_DIR=${KBOX_MOUNT_MAP[TAG_NUMBER - 1]} + + # NUMA + local NUMAS=($(echo $(get_closest_numas ${CPUS[@]}) | tr ' ' '\n' | sort -u | tr '\n' ' ')) + + # 调试端口 + local PORTS=("$((8500+$TAG_NUMBER)):5555") + + # docker额外启动参数 + local EXTRA_RUN_OPTION="" + # 使能硬解设备,若获取到的值为空,则不使能 + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + EXTRA_RUN_OPTION=" ENABLE_HARD_DECODE=${ENABLE_HARD_DECODE}" + elif [ -n "$(lspci -n | grep ${XD_GPU_ID})" ]; then + local idx=$((`echo ${GPUS_RENDER:16}` - 128)) + # docker额外启动参数 + EXTRA_RUN_OPTION+=" --device=/dev/pvr_sync:/dev/pvr_sync:rwm " + EXTRA_RUN_OPTION+=" --device=/dev/ion-$idx:/dev/ion:rwm " + EXTRA_RUN_OPTION+=" --device=${GPUS_RENDER}:/dev/renderD190:rwm" + else + # amdgpu 搭配编码卡使用 + EXTRA_RUN_OPTION=$(netint_run_option $TAG_NUMBER) + fi + + bash $CURRENT_DIR/base_box_aosp15.sh start \ + --name "$CONTAINER_NAME" \ + --cpus "${CPUS[*]}" \ + --numas "${NUMAS[*]}" \ + --gpus "${GPUS_RENDER[*]}" \ + --storage_size_gb "$STORAGE_SIZE_GB" \ + --ram_size_mb "$RAM_SIZE_MB" \ + --ports "${PORTS[*]}" \ + --extra_run_option "$EXTRA_RUN_OPTION" \ + --image "$IMAGE_NAME" \ + --user_data_path "$MOUNT_DIR" \ + --container_data_path "/var/lib/docker" \ + --enable_render_layer "$ENABLE_RENDER_LAYER" + + #enable_hard_decoder $TAG_NUMBER + + # 调整vinput设备权限 + cid=$(docker ps | grep -w ${CONTAINER_NAME} | awk '{print $1}') + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + + if [ -n "$(docker ps -a --format {{.Names}} | grep "$CONTAINER_NAME$")" ]; then + # 等待容器启动 + wait_container_ready ${CONTAINER_NAME} + [ ${?} -eq 1 ] && return + + set -e + enable_netint ${CONTAINER_NAME} + + # 更改容器内部accept_redirects参数配置,禁止ipv6的icmp重定向功能 + disable_ipv6_icmp ${CONTAINER_NAME} + echo -e "---------------------- done ----------------------\n" + fi + if [[ $ENABLE_RENDER_LAYER == "1" ]]; then + # 渲染中间层 + local isEnabled=0; + docker exec -it ${CONTAINER_NAME} sh -c "chmod 777 -R /vendor/shader_cache/" + docker exec -it ${CONTAINER_NAME} sh -c "mkdir -p /data/local/debug/gles" + docker exec -it ${CONTAINER_NAME} sh -c "chmod 755 -R /data/local/debug/" + docker exec -it ${CONTAINER_NAME} sh -c "cp /system/vendor/etc/kbox_render_accelerating_configuration.xml /data/local/tmp" > /dev/null 2>&1 || isEnabled=1 + docker exec -it ${CONTAINER_NAME} sh -c "cp /system/vendor/lib64/hw/RenderAccLayer.kbox.so /data/local/debug/gles" > /dev/null 2>&1 + if [ $? -eq 0 ]; then + docker exec -it ${CONTAINER_NAME} sh -c "setprop debug.gles.layers RenderAccLayer.kbox.so" + else + isEnabled=1 + fi + if [ $isEnabled -eq 1 ]; then + echo -e "\033[31mFailed to enabled render layer! kbox_render_accelerating_configuration.xml or RenderAccLayer.kbox.so may not exist\033[0m" + fi + fi +} + +function main() { + if [ ! -e "$CURRENT_DIR/base_box_aosp15.sh" ]; then + echo "Can not find file base_box_aosp15.sh" + exit 1 + fi + + if [ $1 = "start" ];then + local MIN=$3 MAX=$4 + if [ -z $4 ]; then + MAX=$3 + fi + + local TAG_NUMBER + for TAG_NUMBER in $(seq $MIN $MAX); do + if [ -n "$(docker ps -a --format {{.Names}} | grep "kbox_$TAG_NUMBER$")" ]; then + echo "kbox_$TAG_NUMBER exist!" + else + start_box_by_id $1 $2 $TAG_NUMBER + fi + done + elif [ $1 = "delete" ]; then + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + + local TAG_NUMBER + for TAG_NUMBER in $(seq $MIN $MAX);do + if [ -z "$(docker ps -a --format {{.Names}} | grep "kbox_$TAG_NUMBER$")" ]; then + echo "no container kbox_$TAG_NUMBER!" + else + local MOUNT_DIR=${KBOX_MOUNT_MAP[TAG_NUMBER - 1]} + bash $CURRENT_DIR/base_box_aosp15.sh delete "kbox_$TAG_NUMBER" "$MOUNT_DIR" + fi + done + elif [ $1 = "restart" ]; then + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + local TAG_NUMBER + for TAG_NUMBER in $(seq $MIN $MAX);do + if [ -z "$(docker ps -a --format {{.Names}} | grep "kbox_$TAG_NUMBER$")" ]; then + echo "no container kbox_$TAG_NUMBER!" + else + set +e + enable_hard_decoder $TAG_NUMBER + local MOUNT_DIR=${KBOX_MOUNT_MAP[TAG_NUMBER - 1]} + bash $CURRENT_DIR/base_box_aosp15.sh restart "kbox_$TAG_NUMBER" "$MOUNT_DIR" 3 ${ENABLE_HARD_DECODE} + [ ${?} -eq 1 ] && continue + + enable_netint "kbox_$TAG_NUMBER" + # 调整vinput设备权限 + cid=$(docker ps | grep -w "kbox_$TAG_NUMBER" | awk '{print $1}') + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + if [[ $ENABLE_RENDER_LAYER == "1" ]]; then + docker exec -it "kbox_$TAG_NUMBER" sh -c "cp /system/vendor/lib64/hw/RenderAccLayer.kbox.so /data/local/debug/gles" > /dev/null 2>&1 + if [ $? -eq 0 ]; then + docker exec -it "kbox_$TAG_NUMBER" sh -c "setprop debug.gles.layers RenderAccLayer.kbox.so" + else + echo -e "\033[31mFailed to enabled render layer! RenderAccLayer.kbox.so may not exist\033[0m" + fi + fi + set -e + fi + done + fi +} + +check_environment +check_paras $@ +main "$@" diff --git a/deploy_scripts/base_box_aosp15.sh b/deploy_scripts/base_box_aosp15.sh new file mode 100644 index 0000000000000000000000000000000000000000..9223712689a63c1b2015ef5e9eaf662d2cd57f80 --- /dev/null +++ b/deploy_scripts/base_box_aosp15.sh @@ -0,0 +1,928 @@ +#!/bin/bash +# Copyright Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. +#set -x + +THISDIR=$(readlink -ef $(dirname $0)) +CONTAINERD_CONFIG=$THISDIR/containerd_config +if [ -f "$CONTAINERD_CONFIG" ]; then + DEFAULT_RUNTIME=containerd + RUNTIME_CMD=nerdctl +else + DEFAULT_RUNTIME=docker + RUNTIME_CMD=docker +fi +#=============================================================================== +# Functions +#=============================================================================== +function check_environment() { + # root权限执行此脚本 + if [ "${UID}" -ne 0 ]; then + echo "请使用root权限执行" + exit 1 + fi + + # 支持非当前目录执行 + CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + cd ${CURRENT_DIR} + + # 如果是需要转码的机型,在使用脚本过程中检查转码 + local VENDOR_ID=$(lscpu | grep "Vendor ID:" | grep -v "BIOS" | awk '{print $3}') + if [ x"$VENDOR_ID" == x"0x48" ] || [ x"$VENDOR_ID" == x"HiSilicon" ]; then + check_exagear + fi +} + +function check_exagear() { + # 未注册 + if [ ! -e "/proc/sys/fs/binfmt_misc/ubt_a32a64" ]; then + if [ ! -d "/proc/sys/fs/binfmt_misc/" ]; then + mount -t binfmt_misc none /proc/sys/fs/binfmt_misc + fi + + # 在归档路径下模糊查找 + local UBT_PATHS=($(ls /root/dependency/*/ubt_a32a64)) + if [ ${#UBT_PATHS[@]} -lt 1 ]; then + echo "No ubt_a32a64 file!" + exit 1 + elif [ ${#UBT_PATHS[@]} -gt 1 ]; then + echo "Many ubt_a32a64 files exist! Please check:" + for PA in ${UBT_PATHS[@]}; do + echo "${PA}" + done + exit 1 + fi + + # 恢复exgear文件 + mkdir -p /opt/exagear + chmod -R 700 /opt/exagear + cp -rf ${UBT_PATHS[0]} /opt/exagear/ + cd /opt/exagear + chmod +x ubt_a32a64 + + # 注册转码 续行符后字符串顶格 + echo ":ubt_a32a64:M::\x7fELF\x01\x01\x01\x00\x00\x00\x0"\ +"0\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xf"\ +"f\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00"\ +"\x00\xfe\xff\xff\xff:/opt/exagear/ubt_a32a64:POCF" > /proc/sys/fs/binfmt_misc/register + fi + + # 检查ubt_a32a64版本 + local UBT_VER=($(/opt/exagear/ubt_a32a64 -V |grep -w binary | sed 's/^ExaGear binary translator version: \([^\s]*\)/\1/g' | sed 's/^v//g')) + if [ $UBT_VER \> "2.4.1" ]; then + if [ ! -e "/dev/tango32" ]; then + echo "No tango32!" + exit 1 + fi + fi +} + +function get_lxcfs_path() { + local value + if [ -d "/var/lib/lxc/lxcfs" ]; then + value="/var/lib/lxc/lxcfs" + elif [ -d "/var/lib/lxcfs" ]; then + value="/var/lib/lxcfs" + else + echo "error, fail to get lxcfs path" + exit 1 + fi + + echo ${value} +} + +#CPU文件模拟 +function mock_cpu() { + local CPU_PATH="/var/lib/kbox/cpus/${BOX_NAME}/cpu" + local CPU_NUM=8 + if [ -d "${CPU_PATH}" ];then + umount /var/lib/kbox/cpus/$BOX_NAME/cpu/cpu*/* > /dev/null 2>&1 + rm -rf /var/lib/kbox/cpus/$BOX_NAME + [ $? -ne 0 ] && echo "fail to remove data files /var/lib/kbox/cpus/$BOX_NAME !" && RET="fail" + fi + + mkdir -p ${CPU_PATH} + chmod 755 ${CPU_PATH} + + echo "7" >${CPU_PATH}"/kernel_max" + echo "0-7" >${CPU_PATH}"/possible" + echo "0-7" >${CPU_PATH}"/present" + echo "0-7" >${CPU_PATH}"/online" + + chmod 444 ${CPU_PATH}/kernel_max ${CPU_PATH}/possible ${CPU_PATH}/present ${CPU_PATH}/online + + # mock_cpufreq + mkdir -p ${CPU_PATH}/cpufreq/policy0 ${CPU_PATH}/cpufreq/cpuidle + chmod 755 ${CPU_PATH}/cpufreq ${CPU_PATH}/cpufreq/policy0 ${CPU_PATH}/cpufreq/cpuidle + + echo "$(seq 0 $(($CPU_NUM - 1))|tr 'n' ' ')" >${CPU_PATH}"/cpufreq/policy0/affected_cpus" + echo "1954000" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_max_freq" + echo "1954000" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_cur_freq" + echo "554000" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_min_freq" + echo "0" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_transition_latency" + cat ${CPU_PATH}"/cpufreq/policy0/affected_cpus" >${CPU_PATH}"/cpufreq/policy0/related_cpus" + echo "554000 860000 956000 1042000 1128000 1224000 1320000 1397000 1512000 1628000 1748000 1858000 1954000" >${CPU_PATH}"/cpufreq/policy0/scaling_available_frequencies" + echo "interacitve userspace powersave performance schedutil" >${CPU_PATH}"/cpufreq/policy0/scaling_available_governors" + cat ${CPU_PATH}"/cpufreq/policy0/cpuinfo_cur_freq" >${CPU_PATH}"/cpufreq/policy0/scaling_cur_freq" + echo "cpufreq-dt" >${CPU_PATH}"/cpufreq/policy0/scaling_driver" + echo "performance" >${CPU_PATH}"/cpufreq/policy0/scaling_governor" + cat ${CPU_PATH}"/cpufreq/policy0/cpuinfo_max_freq" >${CPU_PATH}"/cpufreq/policy0/scaling_max_freq" + cat ${CPU_PATH}"/cpufreq/policy0/cpuinfo_min_freq" >${CPU_PATH}"/cpufreq/policy0/scaling_min_freq" + echo "" >${CPU_PATH}"/cpufreq/policy0/scaling_setspeed" + + chmod 444 ${CPU_PATH}/cpufreq/policy0/* + chmod 400 ${CPU_PATH}/cpufreq/policy0/cpuinfo_cur_freq + chmod 644 ${CPU_PATH}/cpufreq/policy0/scaling_governor ${CPU_PATH}/cpufreq/policy0/scaling_setspeed + chmod 660 ${CPU_PATH}/cpufreq/policy0/scaling_max_freq ${CPU_PATH}/cpufreq/policy0/scaling_min_freq + + # mock_cpuidle + mkdir -p ${CPU_PATH}/cpufreq/cpuidle/driver ${CPU_PATH}/cpufreq/cpuidle/state0 ${CPU_PATH}/cpufreq/cpuidle/state1 + chmod 755 ${CPU_PATH}/cpufreq/cpuidle/* + + echo "hisi_cluster0_idle_driver" >${CPU_PATH}"/cpufreq/cpuidle/driver/name" + chmod 444 ${CPU_PATH}"/cpufreq/cpuidle/driver/name" + + echo "ARM64 WFI" >${CPU_PATH}"/cpufreq/cpuidle/state0/desc" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state0/disable" + echo "1" >${CPU_PATH}"/cpufreq/cpuidle/state0/latency" + echo "WFI" >${CPU_PATH}"/cpufreq/cpuidle/state0/name" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state0/power" + echo "1" >${CPU_PATH}"/cpufreq/cpuidle/state0/residency" + echo "$((RANDOM*4+11111))" >${CPU_PATH}"/cpufreq/cpuidle/state0/usage" + echo "$(($(cat ${CPU_PATH}/cpufreq/cpuidle/state0/usage)*666))" >${CPU_PATH}"/cpufreq/cpuidle/state0/time" + + chmod 444 ${CPU_PATH}/cpufreq/cpuidle/state0/* + chmod 644 ${CPU_PATH}/cpufreq/cpuidle/state0/disable + + echo "cpu-sleep-0" >${CPU_PATH}"/cpufreq/cpuidle/state1/desc" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state1/disable" + echo "110" >${CPU_PATH}"/cpufreq/cpuidle/state1/latency" + echo "cpu-sleep-0" >${CPU_PATH}"/cpufreq/cpuidle/state1/name" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state1/power" + echo "3000" >${CPU_PATH}"/cpufreq/cpuidle/state1/residency" + echo "$((RANDOM*+11111))" >${CPU_PATH}"/cpufreq/cpuidle/state1/usage" + echo "$(($(cat ${CPU_PATH}/cpufreq/cpuidle/state1/usage)*22222))" >${CPU_PATH}"/cpufreq/cpuidle/state0/time" + + + chmod 444 ${CPU_PATH}/cpufreq/cpuidle/state1/* + chmod 644 ${CPU_PATH}/cpufreq/cpuidle/state1/disable + + # mock_cpu* + for ((i=0; i<8; i++)); + do + mkdir -p ${CPU_PATH}/cpu$i + chmod 755 ${CPU_PATH}/cpu$i + #其他文件的挂载 + mkdir -p ${CPU_PATH}/cpu$i/hotplug ${CPU_PATH}/cpu$i/power ${CPU_PATH}/cpu$i/regs ${CPU_PATH}/cpu$i/topology + cp /sys/devices/system/cpu/cpu$i/cpu_capacity ${CPU_PATH}/cpu$i/cpu_capacity + mount --bind /sys/devices/system/cpu/cpu$i/hotplug ${CPU_PATH}/cpu$i/hotplug + echo "1" >${CPU_PATH}/cpu$i/online + mount --bind /sys/devices/system/cpu/cpu$i/power ${CPU_PATH}/cpu$i/power + mount --bind /sys/devices/system/cpu/cpu$i/regs ${CPU_PATH}/cpu$i/regs + mount --bind /sys/devices/system/cpu/cpu$i/topology ${CPU_PATH}/cpu$i/topology + mkdir -p ${CPU_PATH}/cpu$i/cpufreq ${CPU_PATH}/cpu$i/cpuidle + mount --bind ${CPU_PATH}/cpufreq/policy0 ${CPU_PATH}/cpu$i/cpufreq + mount --bind ${CPU_PATH}/cpufreq/cpuidle ${CPU_PATH}/cpu$i/cpuidle + done + + RUN_OPTION+="--volume=/var/lib/kbox/cpus/${BOX_NAME}/cpu:/sys/devices/system/cpu:ro" +} + +# 供电模拟:USB供电,未充电状态 +function mock_power_supply() { + local POWER_SUPPLY_PATH="/var/lib/kbox/powers/${BOX_NAME}/power_supply" + + mkdir -p $POWER_SUPPLY_PATH"/Battery" + mkdir -p $POWER_SUPPLY_PATH"/Mains" + mkdir -p $POWER_SUPPLY_PATH"/USB" + mkdir -p $POWER_SUPPLY_PATH"/Wireless" + + echo "100" >$POWER_SUPPLY_PATH"/Battery/capacity" + echo "3945000" >$POWER_SUPPLY_PATH"/Battery/charge_counter" + echo "0" >$POWER_SUPPLY_PATH"/Battery/current_now" + + echo "Good" >$POWER_SUPPLY_PATH"/Battery/health" + echo "1" >$POWER_SUPPLY_PATH"/Battery/online" + + echo "1" >$POWER_SUPPLY_PATH"/Battery/present" + echo "Not charging" >$POWER_SUPPLY_PATH"/Battery/status" + echo "Li-poly" >$POWER_SUPPLY_PATH"/Battery/technology" + echo "260" >$POWER_SUPPLY_PATH"/Battery/temp" + echo "Battery" >$POWER_SUPPLY_PATH"/Battery/type" + echo "4400" > $POWER_SUPPLY_PATH"/Battery/voltage_max" + echo "4356000" >$POWER_SUPPLY_PATH"/Battery/voltage_now" + + echo "500000" >$POWER_SUPPLY_PATH"/USB/current_max" + echo "Good" >$POWER_SUPPLY_PATH"/USB/health" + echo "1" >$POWER_SUPPLY_PATH"/USB/online" + echo "USB" >$POWER_SUPPLY_PATH"/USB/type" + echo "4950000" > $POWER_SUPPLY_PATH"/USB/voltage_max" + + echo "Good" >$POWER_SUPPLY_PATH"/Mains/health" + echo "0" >$POWER_SUPPLY_PATH"/Mains/online" + echo "Mains" >$POWER_SUPPLY_PATH"/Mains/type" + + echo "Good" >$POWER_SUPPLY_PATH"/Wireless/health" + echo "0" >$POWER_SUPPLY_PATH"/Wireless/online" + echo "Wireless" >$POWER_SUPPLY_PATH"/Wireless/type" + + RUN_OPTION+=" --volume=$POWER_SUPPLY_PATH:/sys/class/power_supply:rw " +} + +function check_paras() { + echo "------------------ Kbox Startup ------------------" + + local BOX_NAME CPUS NUMAS GPUS_RENDER STORAGE_SIZE_GB RAM_SIZE_MB PORTS + local EXTRA_RUN_OPTION IMAGE_NAME USER_DATA_PATH CONTAINER_DATA_PATH + local ENABLE_RENDER_LAYER + local PARA_ERROR="" + while :; do + case $1 in + start) shift;; + --name) BOX_NAME=$2; echo "--name) BOX_NAME : $2 "; shift;; + --cpus) CPUS=($2); echo "--cpus) CPUS : $2 "; shift;; + --numas) NUMAS=($2); echo "--numas) NUMAS : $2 "; shift;; + --gpus) GPUS_RENDER=($2); echo "--gpus) GPUS_RENDER : $2 "; shift;; + --storage_size_gb) STORAGE_SIZE_GB=$2; echo "--storage_size_gb) STORAGE_SIZE_GB : $2 "; shift;; + --ram_size_mb) RAM_SIZE_MB=$2; echo "--ram_size_mb) RAM_SIZE_MB : $2 "; shift;; + --ports) PORTS=($2); echo "--ports) PORTS : $2 "; shift;; + --extra_run_option) EXTRA_RUN_OPTION=$2; echo "--extra_run_option) EXTRA_RUN_OPTION : $2 "; shift;; + --image) IMAGE_NAME=$2; echo "--image) IMAGE_NAME : $2 "; shift;; + --user_data_path) USER_DATA_PATH=$2; echo "--user_data_path) USER_DATA_PATH : $2 "; shift;; + --container_data_path) CONTAINER_DATA_PATH=$2; echo "--container_data_path) CONTAINER_DATA_PATH : $2 "; shift;; + --enable_render_layer) ENABLE_RENDER_LAYER=$2; echo "--enable_render_layer) ENABLE_RENDER_LAYER : $2 "; shift;; + --) shift; break;; + -?*) printf 'WARN: Unknown option: %s\n' "$1" >&2; exit 1;; + *) break + esac + + shift + done + + if [ -z $BOX_NAME ]; then + echo "\"--name\" option error, fail: need a kbox name!" + PARA_ERROR="true" + fi + + if [ ${#CPUS[@]} -eq 0 ]; then + echo "\"--cpus\" option error, fail: para empty!" + PARA_ERROR="true" + fi + local CPU + for CPU in ${CPUS[@]}; do + if [ -n "`echo "$CPU" | sed 's/[0-9]//g'`" ]; then + echo "\"--cpus\" option error, fail: cpu parameter must be number!" + PARA_ERROR="true" + fi + if [ $CPU -ge $(lscpu | grep -w "CPU(s)" | head -n 1 | awk '{print $2}') ] || \ + [ $CPU -lt 0 ]; then + echo "\"--cpus\" option error, fail: cpu$CPUS not exist!" + fi + done + + if [ ${#NUMAS[@]} -eq 0 ]; then + echo "\"--numas\" option error, fail: para empty!" + PARA_ERROR="true" + fi + local NUMA + for NUMA in ${NUMAS[@]}; do + if [ -n "`echo "$NUMA" | sed 's/[0-9]//g'`" ]; then + echo "\"--numas\" option error, fail: numa parameter must be number!" + PARA_ERROR="true" + fi + + if [ $NUMA -ge $(lscpu | grep "NUMA node(s)" | awk '{print $3}') ] || \ + [ $NUMA -lt 0 ]; then + echo " \"--numas\" fail: numa$NUMA not exist!" + PARA_ERROR="true" + fi + done + + local GPU + for GPU in ${GPUS_RENDER[@]}; do + if [ ! -e $GPU ]; then + echo "\"--gpus\" error, fail: GPU device $GPU not exist!" + PARA_ERROR="true" + fi + done + + if [ -z "`echo "$STORAGE_SIZE_GB" | sed 's/[0-9]//g'`" ]; then + if [ -z $STORAGE_SIZE_GB ]; then + echo "\"--storage_size_gb\" option error, fail: para empty!" + PARA_ERROR="true" + elif [ $STORAGE_SIZE_GB -le 0 ]; then + echo "\"--storage_size_gb\" option error, fail: storage size must greater than 0 GB!" + PARA_ERROR="true" + fi + else + echo "\"--storage_size_gb\" option error, fail: storage size must be number!" + PARA_ERROR="true" + fi + + if [ -z "`echo "$RAM_SIZE_MB" | sed 's/[0-9]//g'`" ]; then + if [ -z $RAM_SIZE_MB ]; then + echo "\"--ram_size_mb\" option error, fail: para empty!" + PARA_ERROR="true" + elif [ $RAM_SIZE_MB -le 0 ];then + echo "\"--ram_size_mb\" option error, fail: ram size must greater than 0 MB!" + PARA_ERROR="true" + fi + else + echo "\"--ram_size_mb\" option error, fail: ram size must be number!" + PARA_ERROR="true" + fi + + if [ ${#PORTS[@]} -eq 0 ]; then + echo "\"--ports\" option error, fail: para empty!" + PARA_ERROR="true" + fi + local PORT + for PORT in ${PORTS[@]}; do + if [[ "${PORT}" =~ ":" ]]; then + local AGENT_PORT=$(echo ${PORT} | cut -d ':' -f1) + local HOST_PORT=$(echo ${PORT} | cut -d ':' -f2) + if [ -n "`echo "$AGENT_PORT" | sed 's/[0-9]//g'`" ]; then + echo "\"--ports\" option error, fail: agent port must be number!" + PARA_ERROR="true" + fi + + if [ -n "`echo "$HOST_PORT" | sed 's/[0-9]//g'`" ]; then + echo "\"--ports\" option error, fail: host port must be number!" + PARA_ERROR="true" + fi + else + echo "\"--ports\" option error, fail: error port format!" + PARA_ERROR="true" + fi + done + + if [[ "${IMAGE_NAME}" =~ ":" ]]; then + local IMAGE_RE=$(echo ${IMAGE_NAME} | cut -d ':' -f1) + tag=$(echo ${IMAGE_NAME} | cut -d ':' -f2) + $RUNTIME_CMD images | awk '{print $1" "$2}' | grep -w "${IMAGE_RE}" | grep -w "${tag}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "\"--image\" option error, no image ${IMAGE_NAME}!" + PARA_ERROR="true" + fi + else + $RUNTIME_CMD images | awk '{print $3}' | grep -w "${IMAGE_NAME}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "\"--image\" option error, fail: no image ${IMAGE_NAME}!" + PARA_ERROR="true" + fi + fi + + echo "---------------------------------------------------" + if [ "$PARA_ERROR" = "true" ]; then + echo "error: Kbox Start Fail!" + exit 1 + fi +} + +function check_key_process() { + # 检查关键进程是否存在 + local process_name=(system_server zygote zygote64 surfaceflinger) + local cmd="$RUNTIME_CMD exec -i $1 ps -A | egrep -w 'system_server|zygote|zygote64|surfaceflinger' &" + local result=$(wait_cmd "${cmd}") + check_wait_cmd_result "${cmd}" "${result}" + local val + for process in ${process_name[@]}; do + val=$(echo $result |grep -w ${process}'\>') + [ ! -n "$val" ] && echo "$process is null" && return 1 + done + + # 检查关键进程是否重启 + local check_list=(sys.surfaceflinger.has_reboot sys.zygote.has_reboot sys.zygote64.has_reboot) + cmd="$RUNTIME_CMD exec -i $1 getprop |grep '.has_reboot' &" + result=$(wait_cmd "${cmd}" 2>/dev/null ) + check_wait_cmd_result "${cmd}" "${result}" + for property in ${check_list[@]}; do + val=$(echo $result |grep -w ${property}'\>') + [[ "$val" =~ "[1]" ]] && echo "$property has restarted" && return 1 + done + + # 检查服务列表 + cmd="$RUNTIME_CMD exec -i $1 service list |grep -w SurfaceFlinger &" + result=$(wait_cmd "${cmd}") + check_wait_cmd_result "${cmd}" "${result}" + if [[ "$result" =~ "[android.ui.ISurfaceComposer]" ]]; then + return 0 + else + echo "service SurfaceFlinger is not normal" + return 1 + fi +} +# 自动选择回环设备节点 +function chose_loop_device() { + TARGET_LOOPS=39 + MAPPED_LOOPS=0 + num=$(docker ps | grep tcp | wc -l) + CURRENT_LOOP=$((num * 39)) + while [ $MAPPED_LOOPS -lt $TARGET_LOOPS ]; do + # 获取已被占用的loop设备列表(每次循环更新,避免遗漏新占用的设备) + OCCUPIED_LOOPS=$(losetup -a | grep -oP '/dev/loop\K[0-9]+' | sort -n) + # 检查当前loop设备 + # 检查是否已被占用 + if ! echo "$OCCUPIED_LOOPS" | grep -q "^$CURRENT_LOOP$"; then + # 检查设备节点是否存在 + if [ ! -e "/dev/loop$CURRENT_LOOP" ]; then + mknod -m 0660 "/dev/loop$CURRENT_LOOP" b 7 $CURRENT_LOOP + fi + # 添加到映射选项 + RUN_OPTION+=" --device=/dev/loop$CURRENT_LOOP:/dev/loop$CURRENT_LOOP" + MAPPED_LOOPS=$((MAPPED_LOOPS + 1)) + fi + # 移动到下一个loop设备 + CURRENT_LOOP=$((CURRENT_LOOP + 1)) + done +} + + +function start_box() { + ########################## 1. 参数检查 ########################## + check_paras "$@" + ########################## 2. 参数解析 ########################## + while :; do + case $1 in + start) shift;; + --name) local BOX_NAME=$2; shift;; + --cpus) local CPUS=($2); shift;; + --numas) local NUMAS=($2); shift;; + --gpus) local GPUS_RENDER=($2); shift;; + --storage_size_gb) local STORAGE_SIZE_GB=$2; shift;; + --ram_size_mb) local RAM_SIZE_MB=$2; shift;; + --ports) local PORTS=($2); shift;; + --extra_run_option) local EXTRA_RUN_OPTION=$2; shift;; + --image) local IMAGE_NAME=$2; shift;; + --user_data_path) local USER_DATA_PATH=$2; shift;; + --container_data_path) local CONTAINER_DATA_PATH=$2; shift;; + --enable_render_layer) local ENABLE_RENDER_LAYER=$2; shift;; + --) shift; break;; + -?*) printf 'WARN: Unknown option: %s\n' "$1" >&2;; + *) break + esac + shift + done + + ########################## 3.环境初始化 ########################## + if [ $DEFAULT_RUNTIME == "docker" ]; then + CONTAINER_DATA_PATH="/var/lib/docker" + else + CONTAINER_DATA_PATH="/var/lib/containerd" + fi + + # HOOK_PATH + local HOOK_PATH=$CONTAINER_DATA_PATH/hooks + rm -rf ${HOOK_PATH}/${BOX_NAME} + mkdir -p ${HOOK_PATH}/${BOX_NAME} + + # EVENT PATH + local INPUT_EVENT_PATH="/var/run/${BOX_NAME}/input" + mkdir -p $INPUT_EVENT_PATH"/event0" + mkdir -p $INPUT_EVENT_PATH"/event1" + + # 存储隔离 + if [ -z ${USER_DATA_PATH} ]; then + USER_DATA_PATH="/root/mount" + fi + + if [ ! -d "${USER_DATA_PATH}/img" ]; then + mkdir -p ${USER_DATA_PATH}/img + fi + local KBOX_IMG=${USER_DATA_PATH}/img/$BOX_NAME.img + if [ ! -e $KBOX_IMG ]; then + fallocate -l ${STORAGE_SIZE_GB}G $KBOX_IMG + yes | mkfs -t ext4 $KBOX_IMG + fi + KBOX_DATA_PATH="${USER_DATA_PATH}/data/$BOX_NAME" + mkdir -p $KBOX_DATA_PATH + mount $KBOX_IMG $KBOX_DATA_PATH + echo $(($STORAGE_SIZE_GB * 2 * 1024 * 1024)) >$KBOX_DATA_PATH/storage_size + + ########################## 4.容器启动 ########################## + local RUN_OPTION="" + if [ $DEFAULT_RUNTIME == "docker" ]; then + RUN_OPTION+=" -i " + fi + RUN_OPTION+=" -td " + RUN_OPTION+=" --hostname=${BOX_NAME} " + #RUN_OPTION+=" --cap-add=CAP_MKNOD " + RUN_OPTION+=" --cap-add=SETPCAP " + RUN_OPTION+=" --cap-add=AUDIT_WRITE " + RUN_OPTION+=" --cap-add=SYS_CHROOT " + RUN_OPTION+=" --cap-add=CHOWN " + RUN_OPTION+=" --cap-add=DAC_OVERRIDE " + RUN_OPTION+=" --cap-add=FOWNER " + RUN_OPTION+=" --cap-add=SETGID " + RUN_OPTION+=" --cap-add=SETUID " + RUN_OPTION+=" --cap-add=SYSLOG " + RUN_OPTION+=" --cap-add=SYS_ADMIN " + RUN_OPTION+=" --cap-add=WAKE_ALARM " + RUN_OPTION+=" --cap-add=SYS_PTRACE " + RUN_OPTION+=" --cap-add=BLOCK_SUSPEND " + RUN_OPTION+=" --cap-add=MKNOD " + RUN_OPTION+=" --cap-add=KILL " + RUN_OPTION+=" --cap-add=SYS_RESOURCE " + RUN_OPTION+=" --cap-add=NET_RAW " + RUN_OPTION+=" --cap-add=NET_ADMIN " + RUN_OPTION+=" --cap-add=NET_BIND_SERVICE " + RUN_OPTION+=" --cap-add=SYS_NICE " + RUN_OPTION+=" --cap-add=AUDIT_CONTROL " + RUN_OPTION+=" --cap-add=DAC_READ_SEARCH " + RUN_OPTION+=" --cap-add=IPC_LOCK " + RUN_OPTION+=" --cap-add=SYS_MODULE " + RUN_OPTION+=" --security-opt="apparmor:unconfined" " + RUN_OPTION+=" --security-opt="seccomp:unconfined" " + RUN_OPTION+=" --device=/dev/loop-control:/dev/loop-control " + RUN_OPTION+=" --device=/dev/loop0:/dev/loop0 " + RUN_OPTION+=" --name ${BOX_NAME} " + RUN_OPTION+=" -v /sys:/sys " + RUN_OPTION+=" -e CONTAINER_NAME=${BOX_NAME} " + RUN_OPTION+=" -e PATH=/system/bin:/system/xbin " + RUN_OPTION+=" --cidfile ${HOOK_PATH}/${BOX_NAME}/container_id.cid " + RUN_OPTION+=" --cpu-shares=$(lscpu | grep -w "CPU(s)" | head -n 1 | awk '{print $2}') " + + chose_loop_device + + local CPU NUMA TEMP + for CPU in ${CPUS[@]}; do + TEMP+=$CPU"," + done + TEMP=${TEMP: 0: $((${#TEMP} - 1))} + RUN_OPTION+=" --cpuset-cpus=$TEMP " + + TEMP="" + for NUMA in ${NUMAS[@]}; do + TEMP+=$NUMA"," + done + TEMP=${TEMP: 0: $((${#TEMP} - 1))} + RUN_OPTION+=" --cpuset-mems=$TEMP" + + # 内存 +1M,规避依赖UE引擎的游戏在内存设置为4的倍数时会崩溃的问题 + RAM_SIZE_MB=$(($RAM_SIZE_MB + 1)) + RUN_OPTION+=" --memory=${RAM_SIZE_MB}M " + if [ $DEFAULT_RUNTIME == "docker" ]; then + RUN_OPTION+=" --device=/dev/net/tun:/dev/tun:rwm " + else + RUN_OPTION+=" --device=/dev/net/tun:/dev/net/tun:rwm " + fi + RUN_OPTION+=" --device=/dev/ashmem:/dev/ashmem:rwm " + RUN_OPTION+=" --device=/dev/fuse:/dev/fuse:rwm " + RUN_OPTION+=" --device=/dev/uinput:/dev/uinput:rwm " + if [ -c "/dev/ion" ]; then + RUN_OPTION+=" --device=/dev/ion:/dev/ion:rwm " + fi + if [ -c "/dev/i2c-1" ]; then + RUN_OPTION+=" --device=/dev/i2c-1:/dev/i2c-1:rwm " + fi + local i + local VA_SGPU100_ID=":0200" + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + RUN_OPTION+=" --device=/dev/vatools:/dev/vatools:rwm " + RUN_OPTION+=" --device=/dev/va_sync:/dev/va_sync:rwm " + local RENDER_IDX + for (( i=0; i<${#GPUS_RENDER[@]};i++ )); do + RUN_OPTION+=" --device=${GPUS_RENDER[$i]}:${GPUS_RENDER[$i]}:rwm " + RENDER_IDX=$(($(echo "${GPUS_RENDER[$i]}" | tr -cd "[0-9]")-128)) + RUN_OPTION+=" --device=/dev/va${RENDER_IDX}_ctl:/dev/va${RENDER_IDX}_ctl:rwm " + RUN_OPTION+=" --device=/dev/va_video${RENDER_IDX}:/dev/va_video${RENDER_IDX}:rwm " + RUN_OPTION+=" --device=/dev/vacc${RENDER_IDX}:/dev/vacc${RENDER_IDX}:rwm " + done + else + for (( i=0; i<${#GPUS_RENDER[@]};i++ )); do + RUN_OPTION+=" --device=${GPUS_RENDER[$i]}:/dev/dri/renderD$((128 + $i)):rwm " + done + fi + if [ -e "/dev/tango32" ]; then + RUN_OPTION+=" --device=/dev/tango32:/dev/tango32:rwm " + fi + RUN_OPTION+=" --volume=$KBOX_DATA_PATH/cache:/cache:rw " + RUN_OPTION+=" --volume=$KBOX_DATA_PATH/data:/data:rw " + RUN_OPTION+=" --volume=$INPUT_EVENT_PATH/event0:/dev/input/event0:rw " + RUN_OPTION+=" --volume=$INPUT_EVENT_PATH/event1:/dev/input/event1:rw " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/diskstats:/proc/diskstats:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/meminfo:/proc/meminfo:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/stat:/proc/stat:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/swaps:/proc/swaps:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/uptime:/proc/uptime:ro " + RUN_OPTION+=" --volume=$KBOX_DATA_PATH/storage_size:/storage_size:rw " + if [ -f default.prop_$BOX_NAME ]; then + RUN_OPTION+=" --volume=$THISDIR/default.prop_$BOX_NAME:/kbox_prop/default.prop:rw " + fi + if [ -f build.prop ]; then + RUN_OPTION+=" --volume=$THISDIR/build.prop:/kbox_prop/build.prop:rw " + fi + if [[ $ENABLE_RENDER_LAYER == "1" ]]; then + RUN_OPTION+=" --volume=${USER_DATA_PATH}/shader_cache/:/vendor/shader_cache/:rw " + fi + mock_cpu + mock_power_supply + local PORT + for PORT in ${PORTS[@]}; do + RUN_OPTION+=" -p $PORT " + done + RUN_OPTION+=" --sysctl net.ipv6.conf.all.accept_redirects=0" + # 额外的选项 + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + # VA GPU 使用该参数传递是否使能硬解,其余情况下传递硬解设备信息。 + ENABLE_HARD_DECODE=$(echo "${EXTRA_RUN_OPTION}" | grep -oP '(?<=ENABLE_HARD_DECODE=)[01]') + EXTRA_RUN_OPTION=${EXTRA_RUN_OPTION% *} + fi + RUN_OPTION+=" $EXTRA_RUN_OPTION " + $RUNTIME_CMD run $RUN_OPTION --device-cgroup-rule "c *:* rwm" $IMAGE_NAME /init + + if [ $DEFAULT_RUNTIME == "containerd" ]; then + $RUNTIME_CMD exec -i ${BOX_NAME} ln -s /dev/net/tun /dev/tun + fi + + # 支持Android系统属性可定制 + # local.prop用于修改定制属性,但该文件不是一定存在,需要用户手动生成。 + if [ -e "$CURRENT_DIR/local.prop" ]; then + $RUNTIME_CMD cp $CURRENT_DIR/local.prop ${BOX_NAME}:/data + $RUNTIME_CMD exec ${BOX_NAME} chmod 400 /data/local.prop + fi + + # VA GPU需要配置相关属性、修改设备的权限, 否则会导致容器无法启动, 当前VA GPU仅支持一张卡,故使用 GPUS_RENDER[0] + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + $RUNTIME_CMD cp ${BOX_NAME}:/system/vendor/build.prop build.prop_${BOX_NAME} + if [ $ENABLE_HARD_DECODE -eq 1 ];then + sed -i "s/ro.hardware.omxsoftdecode=1/ro.hardware.omxsoftdecode=0/g" build.prop_${BOX_NAME} + else + sed -i "s/ro.hardware.omxsoftdecode=0/ro.hardware.omxsoftdecode=1/g" build.prop_${BOX_NAME} + fi + $RUNTIME_CMD cp build.prop_${BOX_NAME} ${BOX_NAME}:/system/vendor/build.prop + rm -rf ./build.prop_${BOX_NAME} + fi + local cid=$($RUNTIME_CMD ps | grep -w " ${BOX_NAME}" | awk '{print $1}') + local BINDER_MAJOR_ID=$(cat /proc/devices | grep binder | awk '{print $1}') + if [ $DEFAULT_RUNTIME == "docker" ]; then + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/docker/$cid*/cgroup.clone_children + else + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/default/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/default/$cid*/cgroup.clone_children + fi +} + +function delete_box() { + local BOX_NAME=$1 + local USER_DATA_PATH=$2 + local keep_data=0 + if [ $3 ] && [ $3 -eq 1 ]; then + keep_data=1 + fi + local RET="true" + local umount_try=30 + local rm_try=30 + set +e + # 删除容器 + if [ -n "$("$RUNTIME_CMD" ps -a --format {{.Names}} | grep "$BOX_NAME$")" ]; then + while [ $rm_try -gt 1 ] + do + $RUNTIME_CMD kill $BOX_NAME > /dev/null 2>&1 + $RUNTIME_CMD rm $BOX_NAME > /dev/null 2>&1 + if [ $? -ne 0 ]; then + rm_try=$((rm_try - 1)) + RET="fail" + sleep 1 + else + echo "remove container $BOX_NAME OK" + RET="true" + break + fi + done + fi + + # 删除cpu/文件 + umount /var/lib/kbox/cpus/$BOX_NAME/cpu/cpu*/* > /dev/null 2>&1 + rm -rf /var/lib/kbox/cpus/$BOX_NAME + [ $? -ne 0 ] && echo "fail to remove data files /var/lib/kbox/cpus/$BOX_NAME !" && RET="fail" + + # 删除power_supply文件 + rm -rf /var/lib/kbox/powers/${BOX_NAME} + + # 删除数据文件 + if [ -z ${USER_DATA_PATH} ]; then + USER_DATA_PATH="/root/mount" + fi + + if [ -d "$USER_DATA_PATH/data/$BOX_NAME" ]; then + while [ $umount_try -gt 1 ] + do + umount $USER_DATA_PATH/data/$BOX_NAME > /dev/null 2>&1 + [ $? -ne 0 ] && echo "$BOX_NAME is already umounted!" + mount | grep -w "$USER_DATA_PATH/data/$BOX_NAME" + if [ $? -eq 0 ]; then + umount_try=$((umount_try - 1)) + sleep 1 + else + echo "umounted $BOX_NAME OK" + break + fi + done + rm -rf $USER_DATA_PATH/data/$BOX_NAME > /dev/null 2>&1 + [ $? -ne 0 ] && echo "fail to remove data files $USER_DATA_PATH/data/$BOX_NAME !" && RET="fail" + fi + + # 删除数据img文件 + if [ -e "$USER_DATA_PATH/img/$BOX_NAME.img" ] && [ $keep_data -ne 1 ]; then + rm -rf $USER_DATA_PATH/img/$BOX_NAME.img > /dev/null 2>&1 + [ $? -ne 0 ] && echo "fail to remove image file $USER_DATA_PATH/img/$BOX_NAME.img !" && RET="fail" + fi + + # 删除input event path + if [ -d /var/run/$BOX_NAME ]; then + rm -rf /var/run/${BOX_NAME} > /dev/null 2>&1 + [ $? -ne 0 ] && echo "fail to remove event path /var/run/${BOX_NAME} !" && RET="fail" + fi + + if [ $RET == "true" ];then + echo "container ${BOX_NAME} is deleted successfully." + fi +} + +function wait_async_cmd() { + eval $1 + local pid=$(jobs -rp) + local count_time=0 + while true; do + local count=$(jobs -rp | wc -l) + if [ ${count} -eq 0 ]; then + wait ${pid} + # $?表示wait的返回状态,用于获取eval $1执行的命令是否执行成功,执行成功返回0 + if [ $? -ne 0 ]; then + echo -2 # 命令执行失败 + fi + break + fi + + if [ ${count_time} -gt 8 ]; then + kill -9 ${pid} + echo -1 + break + fi + + sleep 0.5 + count_time=$((count_time + 1)) + done +} + +function wait_cmd() { + local count_time=0 + while true; do + local result=$(wait_async_cmd "$1") + if [ "$result" != "-1" ]; then + echo ${result} + break + fi + + if [ ${count_time} -gt 3 ]; then + echo -1 + break + fi + count_time=$((count_time + 1)) + done +} + +check_wait_cmd_result() { + local cmd=$1 + local result=$2 + if [ "$result" == "-1" ]; then + echo "cmd \"${cmd}\" wait_cmd timeout" + fi +} + +function restart_box() { + local BOX_NAME=$1 + local USER_DATA_PATH=$2 + + local restart_times=3 # 默认最大重启次数为三次 + if [ $# -eq 3 ]; then + restart_times=$3 + fi + local ENABLE_HARD_DECODE=0 + if [ $# -eq 4 ]; then + ENABLE_HARD_DECODE=$4 + fi + + set +e + if [ -z ${USER_DATA_PATH} ]; then + USER_DATA_PATH="/root/mount" + fi + + echo "mount ${BOX_NAME}.img" + mount ${USER_DATA_PATH}/img/${BOX_NAME}.img ${USER_DATA_PATH}/data/${BOX_NAME} >/dev/null + + mock_cpu + + $RUNTIME_CMD inspect ${BOX_NAME} >/dev/null + if [ $? -ne 0 ]; then + # 无容器判断 + break + fi + + for i in $(seq 1 $restart_times) + do + local should_restart=0 # 0为不应该再重启,1为需要再次重启 + $RUNTIME_CMD stop -t 0 ${BOX_NAME} + echo "${BOX_NAME} begins restarting the $i times!" + RUN_OPTION+="" + chose_loop_device + $RUNTIME_CMD start ${BOX_NAME} + + if [ $DEFAULT_RUNTIME == "containerd" ]; then + $RUNTIME_CMD exec -i ${BOX_NAME} ln -s /dev/net/tun /dev/tun + fi + for j in $(seq 1 3) + do { + $RUNTIME_CMD inspect ${BOX_NAME} --format {{.State.Status}} |grep running + if [ $? -eq 0 ]; then + # 等待容器状态为 running + break + fi + sleep 1 + } done + + local execOneTime=true + local VA_SGPU100_ID=":0200" + + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ] && [ execOneTime ]; then + $RUNTIME_CMD cp ${BOX_NAME}:/system/vendor/build.prop build.prop_${BOX_NAME} + if [ $ENABLE_HARD_DECODE -eq 1 ];then + sed -i "s/ro.hardware.omxsoftdecode=1/ro.hardware.omxsoftdecode=0/g" build.prop_${BOX_NAME} + else + sed -i "s/ro.hardware.omxsoftdecode=0/ro.hardware.omxsoftdecode=1/g" build.prop_${BOX_NAME} + fi + $RUNTIME_CMD cp build.prop_${BOX_NAME} ${BOX_NAME}:/system/vendor/build.prop + rm -rf ./build.prop_${BOX_NAME} + execOneTime=false + fi + local cid=$($RUNTIME_CMD ps | grep -w " ${BOX_NAME}" | awk '{print $1}') + local BINDER_MAJOR_ID=$(cat /proc/devices | grep binder | awk '{print $1}') + if [ $DEFAULT_RUNTIME == "docker" ]; then + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/docker/$cid*/cgroup.clone_children + else + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/default/$cid*/devices.allow) + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/default/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/default/$cid*/cgroup.clone_children + fi + + # 支持Android系统属性可定制 + # local.prop用于修改定制属性,但该文件不是一定存在,需要用户手动生成。 + if [ -e "$CURRENT_DIR/local.prop" ]; then + $RUNTIME_CMD cp $CURRENT_DIR/local.prop ${BOX_NAME}:/data + $RUNTIME_CMD exec ${BOX_NAME} chmod 400 /data/local.prop + fi + + local count_time=0 + while true; do + local cmd="$RUNTIME_CMD exec -i ${BOX_NAME} getprop sys.boot_completed | grep 1 &" + local result=$(wait_cmd "${cmd}" 2>/dev/null) + check_wait_cmd_result "${cmd}" "${result}" + if [ "${result}" == "1" ]; then + # 等待容器启动完成 + check_key_process ${BOX_NAME} + [ ${?} -ne 0 ] && echo "${BOX_NAME} check key process fail" && should_restart=1 + break + fi + if [ ${count_time} -gt 50 ]; then + echo -e "\033[1;31m reStart check timed out,${BOX_NAME} unable to restart\033[0m" + should_restart=1 + break + fi + sleep 1 + count_time=$((count_time + 1)) + done + + if [ $i -eq $restart_times ] && [ $should_restart -eq 1 ];then + echo "${BOX_NAME} start failed!" + return 1 + fi + local cmd="$RUNTIME_CMD exec -i ${BOX_NAME} logcat -d |grep \"addInterfaceToNetwork() failed\" &" + local result=$(wait_async_cmd "${cmd}") + if [ "${result}" == "-1" ];then + echo "${BOX_NAME} wait_async_cmd logcat timeout" + elif [ "${result}" == "-2" ];then + # 无异常日志, 且检查关键进程均无异常,退出重启流程 + if [ $should_restart -eq 0 ]; then + break + fi + fi + done +} + +check_environment +CMD=$1; shift +case $CMD in + start) start_box "$@";; + delete) delete_box "$@";; + restart) restart_box "$@";; + wait_async_cmd) wait_async_cmd "$@";; + chk_key_process) check_key_process "$@";; + *) echo "command must be \"start\", \"delete\", \"restart\", \"wait_async_cmd\" or \"chk_key_process\"";; +esac diff --git a/deploy_scripts/kbox_config.cfg b/deploy_scripts/kbox_config.cfg new file mode 100644 index 0000000000000000000000000000000000000000..47019e0633187d922438aa417acb3c00e2fd5458 --- /dev/null +++ b/deploy_scripts/kbox_config.cfg @@ -0,0 +1,915 @@ +#! /bin/bash +# Copyright Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. +# 启动脚本配置文件,可配置GPU、CPU等 + +#是否使能硬件解码功能, 1表示使能,其他值默认不使能 +ENABLE_HARD_DECODE=0 + +#是否使能渲染中间层,1表示使能,其他值默认不使能 +ENABLE_RENDER_LAYER=0 + +#硬件解码卡类型:0:T432 1:Quadra +HARD_DECODE_TYPE=2 + +# NETINT编解码卡设备节点, 启用硬解或者重启时启用硬解都需在第一次启动时增加设备节点,以下为示意 +# NETINT0="/dev/nvme0,/dev/nvme0n1,/dev/nvme1,/dev/nvme1n1,/dev/nvme2,/dev/nvme2n1,/dev/nvme3,/dev/nvme3n1" +# NETINT1="/dev/nvme4,/dev/nvme4n1,/dev/nvme5,/dev/nvme5n1,/dev/nvme6,/dev/nvme6n1,/dev/nvme7,/dev/nvme7n1" +NETINT0="" +NETINT1="" + +KBOX_DEC_MAP=( + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" +) + +KBOX_GPU_MAP=( +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +) + +KBOX_XD_GPU_MAP_4RENDERS=( +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +) + +KBOX_XD_GPU_MAP_8RENDERS=( +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +) + +KBOX_XD_GPU_MAP_16RENDERS=( +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +) + +KBOX_XD_GPU_MAP_24RENDERS=( +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD144 +/dev/dri/renderD145 +/dev/dri/renderD146 +/dev/dri/renderD147 +/dev/dri/renderD148 +/dev/dri/renderD149 +/dev/dri/renderD150 +/dev/dri/renderD151 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD144 +/dev/dri/renderD145 +/dev/dri/renderD146 +/dev/dri/renderD147 +/dev/dri/renderD148 +/dev/dri/renderD149 +/dev/dri/renderD150 +/dev/dri/renderD151 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD144 +/dev/dri/renderD145 +/dev/dri/renderD146 +/dev/dri/renderD147 +/dev/dri/renderD148 +/dev/dri/renderD149 +/dev/dri/renderD150 +/dev/dri/renderD151 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD144 +/dev/dri/renderD145 +/dev/dri/renderD146 +/dev/dri/renderD147 +/dev/dri/renderD148 +/dev/dri/renderD149 +/dev/dri/renderD150 +/dev/dri/renderD151 +/dev/dri/renderD140 +/dev/dri/renderD141 +) + +KBOX_VA_GPU_MAP=( +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +) +KBOX_MOUNT_MAP=( +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +) +KBOX_CPUSET_MAP=( +"4 5" +"4 5" +"6 7" +"6 7" +"8 9" +"8 9" +"10 11" +"10 11" +"12 13" +"12 13" +"14 15" +"14 15" +"16 17" +"16 17" +"18 19" +"18 19" +"20 21" +"20 21" +"22 23" +"22 23" +"24 25" +"24 25" +"26 27" +"26 27" +"36 37" +"36 37" +"38 39" +"38 39" +"40 41" +"40 41" +"42 43" +"42 43" +"44 45" +"44 45" +"46 47" +"46 47" +"48 49" +"48 49" +"50 51" +"50 51" +"52 53" +"52 53" +"54 55" +"54 55" +"56 57" +"56 57" +"58 59" +"58 59" +"60 61" +"60 61" +"68 69" +"68 69" +"70 71" +"70 71" +"72 73" +"72 73" +"74 75" +"74 75" +"76 77" +"76 77" +"78 79" +"78 79" +"80 81" +"80 81" +"82 83" +"82 83" +"84 85" +"84 85" +"86 87" +"86 87" +"88 89" +"88 89" +"90 91" +"90 91" +"100 101" +"100 101" +"102 103" +"102 103" +"104 105" +"104 105" +"106 107" +"106 107" +"108 109" +"108 109" +"110 111" +"110 111" +"112 113" +"112 113" +"114 115" +"114 115" +"116 117" +"116 117" +"118 119" +"118 119" +"120 121" +"120 121" +"122 123" +"122 123" +"124 125" +"124 125" +) diff --git a/deploy_scripts/kbox_maintainer.py b/deploy_scripts/kbox_maintainer.py new file mode 100644 index 0000000000000000000000000000000000000000..4c9da1c15c59e84f74b35d148a9a9bbc9ba6ec79 --- /dev/null +++ b/deploy_scripts/kbox_maintainer.py @@ -0,0 +1,84 @@ +import sys +import os +from argparse import ArgumentParser + +try: + sys.path.insert(0, os.getcwd()) + from kbox_maintainer import check + from kbox_maintainer import recover + from kbox_maintainer import log + from kbox_maintainer import resource +except KeyboardInterrupt: + raise SystemExit() + +if __name__ == "__main__": + + parser = ArgumentParser( + description="===Kbox Maintainment tool set usage===", + epilog="Hope this tool is helpful :)", + allow_abbrev=False, + ) + + subparsers = parser.add_subparsers( + title='maintainer options', + description='option is required to run different task', + metavar='option', + dest='option', + help='help details', + required=True + ) + + check_parser = subparsers.add_parser( + 'check', + help='check container(s) status' + ) + + check_parser.add_argument( + "containers", + nargs='*', + metavar="containers", + help='container name or id, check all when no container is specified' + ) + check_parser.set_defaults(func=check) + + recover_parser = subparsers.add_parser( + 'recover', + help='recover container(s)' + ) + + recover_parser.add_argument( + "containers", + nargs='*', + metavar="containers", + help='container name or id, recover all when no container is specified' + ) + recover_parser.set_defaults(func=recover) + + log_parser = subparsers.add_parser( + 'log', + help='log container(s)' + ) + + log_parser.add_argument( + "containers", + nargs='*', + metavar="containers", + help='container name or id, log all when no container is specified' + ) + log_parser.set_defaults(func=log) + + resource_parser = subparsers.add_parser( + 'resource', + help='resource container(s)' + ) + + resource_parser.add_argument( + "containers", + nargs='*', + metavar="containers", + help='container name or id, resource all when none is specified' + ) + resource_parser.set_defaults(func=resource) + + args = parser.parse_args(sys.argv[1:]) + args.func(args.containers) diff --git a/deploy_scripts/kbox_maintainer/__init__.py b/deploy_scripts/kbox_maintainer/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..431958e875b27deeaecdfc0d3f2a176bab01b984 --- /dev/null +++ b/deploy_scripts/kbox_maintainer/__init__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# coding: utf-8 +""" +Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +kbox_maintainer is a tool set aiming at Kbox maintainment. + +""" + +from kbox_maintainer.checker import check +from kbox_maintainer.checker import recover +from kbox_maintainer.logger import log +from kbox_maintainer.logger import resource + +__all__ = ["check", "recover", "log", "resource"] \ No newline at end of file diff --git a/deploy_scripts/kbox_maintainer/checker/__init__.py b/deploy_scripts/kbox_maintainer/checker/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a2c8b7f6f74a0457be2035f96dde9b272376f75c --- /dev/null +++ b/deploy_scripts/kbox_maintainer/checker/__init__.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# coding: utf-8 +""" +Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +Cherker is to check the system and make sure everything is OK. + +check: check system status and container status. + +recover: check and try to recover system status and container status. +""" + +from kbox_maintainer.checker.api import check +from kbox_maintainer.checker.api import recover + +__all__ = ["check", "recover"] diff --git a/deploy_scripts/kbox_maintainer/checker/api.py b/deploy_scripts/kbox_maintainer/checker/api.py new file mode 100644 index 0000000000000000000000000000000000000000..95f29479751a747f32123e91bf1dba1ba0bff9ab --- /dev/null +++ b/deploy_scripts/kbox_maintainer/checker/api.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# -*- encoding:utf-8 -*- +# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +import sys +import logging +from kbox_maintainer.checker.checker import Checker + + +def check(containers): + print(containers) + if not sys.platform.startswith('linux'): + logging.critical("This tool only support linux platform") + exit(0) + + if not Checker.check_exagear(): + logging.error( + "exagear not register, using [kbox_maintainer.py recover]") + return + + checker = Checker() + checker.check_containers(containers) + + +def recover(containers): + print(containers) + if not sys.platform.startswith('linux'): + logging.critical("This tool only support linux platform") + exit(0) + + if not Checker.check_exagear() and not Checker.recover_exagear(): + logging.fatal( + "exagear cannot recover!!!") + return + + checker = Checker() + checker.recover_containers(containers) diff --git a/deploy_scripts/kbox_maintainer/checker/checker.py b/deploy_scripts/kbox_maintainer/checker/checker.py new file mode 100644 index 0000000000000000000000000000000000000000..02a017277e8b59f13527e83cda03947c81b76e97 --- /dev/null +++ b/deploy_scripts/kbox_maintainer/checker/checker.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +# -*- encoding:utf-8 -*- +# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +import logging +import subprocess +import stat +from pathlib import Path +import docker +from os import uname +import re +from cpuinfo import get_cpu_info + +class Checker(object): + + def __init__(self): + self.__client = docker.from_env() + + @staticmethod + def _check_one_container(container): + container.reload() + if container.status != 'running': + print("container[short_id:{}, name:{}] is {}".format( + container.short_id, container.name, container.status)) + return False + + exit_code, output = container.exec_run("getprop sys.boot_completed") + if exit_code != 0: + print("container[name:{}] getprop failed, exit_code={}".format( + container.name, exit_code)) + return False + + if output != b'1\n': + print("container[name:{}] system boot is incomplete!!!".format( + container.name)) + return False + + process_name=["zygote", "zygote64", "surfaceflinger", "system_server"] + exit_code, output = container.exec_run("ps -a") + if exit_code != 0: + print("container[name:{}] get process failed, exit_code={}".format( + container.name, exit_code)) + return False + + for process in process_name: + patt = ' ' + process + '\n' + matchobj = re.search(patt, output.decode()) + if not matchobj: + print("container[name:{}] process[{}] is null!!!".format(container.name, process)) + return False + + check_list=["sys.surfaceflinger.has_reboot", "sys.zygote.has_reboot", "sys.zygote64.has_reboot"] + for proper in check_list: + exit_code, output = container.exec_run("getprop " + proper) + if exit_code != 0: + print("container[name:{}] get sys.prop[{}] failed, exit_code={}".format( + container.name, proper, exit_code)) + return False + if output == b'1\n': + print("container[name:{}] {}!!!".format(container.name, proper)) + return False + + exit_code, output = container.exec_run("service list |grep -w SurfaceFlinger") + if exit_code != 0: + print("container[name:{}] get service SurfaceFlinger failed, exit_code={}".format( + container.name, exit_code)) + return False + if str(output).find("[android.ui.ISurfaceComposer]") == -1: + print("container[name:{}] check service SurfaceFlinger failed!!!".format( + container.name)) + return False + + return True + + def check_containers(self, containers): + if containers: + containers_list = [self.__client.containers.get( + container) for container in containers] + else: + containers_list = self.__client.containers.list(all=True) + + unhealthy_containers = [] + for container in containers_list: + healthy = Checker._check_one_container(container) + if not healthy: + unhealthy_containers.append(container) + + print("===container check report===\n") + print("Total checked containers: {}\n".format(len(containers_list))) + if unhealthy_containers: + print("unhealth containers name:") + print([container.name for container in unhealthy_containers]) + else: + print("All the checked containers are healthy!") + + return unhealthy_containers + + @staticmethod + def _recover_one_container(container): + # exec android_kbox.sh scripts + container_no = container.name.split('_')[1] + cmd = Path.cwd() / "android_kbox.sh" + base_cmd = Path.cwd() / "base_box.sh" + if not cmd.is_file() or not base_cmd.is_file(): + logging.fatal("{} is not found".format(str(cmd))) + return + + cmd.chmod(mode=cmd.stat().st_mode | stat.S_IXUSR) + base_cmd.chmod(mode=base_cmd.stat().st_mode | stat.S_IXUSR) + + subprocess.run([str(cmd), "restart", container_no]) + + def recover_containers(self, containers): + unhealthy_containers = self.check_containers(containers) + if not unhealthy_containers: + return [] + + for container in unhealthy_containers: + Checker._recover_one_container(container) + + unrecover_containers = [] + for container in unhealthy_containers: + if not Checker._check_one_container(container): + unrecover_containers.append(container) + + print("===container recover report===\n") + if unrecover_containers: + print("unrecover containers name:") + print([container.name for container in unrecover_containers]) + else: + print("All the containers are recovered!") + + return unrecover_containers + + @staticmethod + def check_exagear(): + exagear = Path("/proc/sys/fs/binfmt_misc/ubt_a32a64") + return exagear.is_file() and exagear.read_text().startswith("enabled") + + @staticmethod + def recover_exagear(): + # exec android_kbox.sh scripts + cmd = Path.cwd() / "android_kbox.sh" + base_cmd = Path.cwd() / "base_box.sh" + if not cmd.is_file() or not base_cmd.is_file(): + logging.fatal("{} is not found".format(str(cmd))) + return + + cmd.chmod(mode=cmd.stat().st_mode | stat.S_IXUSR) + base_cmd.chmod(mode=base_cmd.stat().st_mode | stat.S_IXUSR) + + subprocess.run([str(cmd), "restart"]) + return Checker.check_exagear() diff --git a/deploy_scripts/kbox_maintainer/logger/__init__.py b/deploy_scripts/kbox_maintainer/logger/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..6f70c000863e8fcd8f2faf1ecc309fec886dc7d6 --- /dev/null +++ b/deploy_scripts/kbox_maintainer/logger/__init__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# coding: utf-8 +""" +Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +logger is to collect the needed log. + +log: run to collect logs (both hostOS and guestOS). + +""" + +from kbox_maintainer.logger.api import log +from kbox_maintainer.logger.api import resource + +__all__ = ["log", "resource"] \ No newline at end of file diff --git a/deploy_scripts/kbox_maintainer/logger/api.py b/deploy_scripts/kbox_maintainer/logger/api.py new file mode 100644 index 0000000000000000000000000000000000000000..819d46b5ed4e6aaf121454d23a5fe785bc3d954b --- /dev/null +++ b/deploy_scripts/kbox_maintainer/logger/api.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# -*- encoding:utf-8 -*- +# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +import sys +import logging +from kbox_maintainer.logger.logger import Logger + + +def log(containers): + print(containers) + if not sys.platform.startswith('linux'): + logging.critical("This tool only support linux platform") + exit(0) + logger = Logger() + logger.log_containers(containers) + +def resource(containers): + print(containers) + if not sys.platform.startswith('linux'): + logging.critical("This tool only support linux platform") + exit(0) + logger = Logger() + logger.resource_containers(containers) \ No newline at end of file diff --git a/deploy_scripts/kbox_maintainer/logger/logger.py b/deploy_scripts/kbox_maintainer/logger/logger.py new file mode 100644 index 0000000000000000000000000000000000000000..52ce45ea5e870ba40c101560395408fbeaefa67a --- /dev/null +++ b/deploy_scripts/kbox_maintainer/logger/logger.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python3 +# -*- encoding:utf-8 -*- +# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +import logging +import subprocess +from pathlib import Path +from shutil import make_archive +from shutil import copy +from shutil import rmtree +from shutil import copytree +from datetime import datetime +from tempfile import mkdtemp +import docker + + +class Logger(object): + def __init__(self): + self.__client = docker.from_env() + self.log_path = Path(mkdtemp(suffix='_log', prefix='kbox_', dir=str(Path.cwd()))) + self.guestos_log_path = self.log_path / "guestos" + self.hostos_log_path = self.log_path / "hostos" + self.guestos_log_path.mkdir(parents=True, exist_ok=True) + self.hostos_log_path.mkdir(parents=True, exist_ok=True) + + def _get_data_mount_path(self, container): + container_binds = self.__client.api.inspect_container(container.name)["HostConfig"]['Binds'] + for bind in container_binds: + if "data:/data:rw" in bind: + return bind.split(':')[0] + + raise ValueError("container {} not find data mount inspect".format(container.name)) + + def _run_cmd(self, container, cmd, to_file=False): + if container.status != 'running': + print("container[short_id:{}, name:{}] is {}".format( + container.short_id, container.name, container.status)) + return False + + if not cmd: + logging.error("invalid cmd") + return False + + exit_code, output = container.exec_run(cmd) + if exit_code != 0: + logging.error("cmd[{}] run failed".format(cmd)) + return False + + if to_file: + log_name = cmd.replace(" ", "_") + ".log" + file_path = self.guestos_log_path / container.name / log_name + file_path.write_text(output.decode()) + return True + + def _log_one_container(self, container): + container.reload() + if container.status != 'running': + print("container[short_id:{}, name:{}] is {}".format( + container.short_id, container.name, container.status)) + return False + + container_log = self.guestos_log_path / container.name + container_log.mkdir(parents=True, exist_ok=True) + docker_inspect_log = container_log / "docker_inspect.log" + with docker_inspect_log.open(mode="w") as f: + docker_inspect_proc = subprocess.run( + ["docker", "inspect", container.name], stdout=f) + if docker_inspect_proc.returncode != 0: + logging.fatal("docker inspect failed") + return False + + log_path = "/data/" + self.log_path.parts[-1] + ret_val = self._run_cmd(container, "mkdir -p " + log_path) \ + and self._run_cmd(container, "logcat -d -f " + log_path + "/logcat.log") \ + and self._run_cmd(container, "cp -r /data/anr " + log_path) \ + and self._run_cmd(container, "getprop", to_file=True) \ + and self._run_cmd(container, "dumpsys activity", to_file=True) \ + and self._run_cmd(container, "dumpsys meminfo", to_file=True) \ + and self._run_cmd(container, "dumpsys input", to_file=True) \ + and self._run_cmd(container, "ps -a", to_file=True) \ + and self._run_cmd(container, "cp -r /proc/cpuinfo " + log_path) \ + and self._run_cmd(container, "dumpsys meminfo", to_file=True) \ + and self._run_cmd(container, "top -n1", to_file=True) \ + and self._run_cmd(container, "df -h", to_file=True) \ + and self._run_cmd(container, "lspci", to_file=True) + + src_path = self._get_data_mount_path(container) + "/" + self.log_path.parts[-1] + dst_path = str(container_log / "data") + copytree(src_path, dst_path) + + return ret_val and self._run_cmd(container, "rm -rf " + log_path) + + def log_containers(self, containers): + var_log = self.hostos_log_path / "var_log" + make_archive(str(var_log), "tar", '/var/log') + + dmesg_log = self.hostos_log_path / "dmesg.log" + with dmesg_log.open(mode="w") as f: + dmesg_proc = subprocess.run(["dmesg", "-T"], stdout=f) + if dmesg_proc.returncode != 0: + logging.fatal("dmesg failed") + return + + docker_stats_log = self.hostos_log_path / "docker_stats.log" + with docker_stats_log.open(mode="w") as f: + docker_stats_proc = subprocess.run( + ["docker", "stats", "--no-stream"], stdout=f) + if docker_stats_proc.returncode != 0: + logging.fatal("docker stats failed") + return + + admgpu_pm_info_pathes = Path( + "/sys/kernel/debug/dri/").glob('*/amdgpu_pm_info') + for src_path in admgpu_pm_info_pathes: + dst_path = self.hostos_log_path / \ + "amdgpu_pm_info_{}".format(src_path.parts[-2]) + copy(str(src_path), str(dst_path)) + + if containers: + containers_list = [self.__client.containers.get( + container) for container in containers] + else: + containers_list = self.__client.containers.list(all=True) + + if not containers_list: + logging.fatal("No container found") + return + + log_failed_containers = [] + for container in containers_list: + log_ok = self._log_one_container(container) + if not log_ok: + log_failed_containers.append(container) + + print("===container log report===\n") + print("Total containers: {}\n".format(len(containers_list))) + if log_failed_containers: + print("log failed containers name:") + print([container.name for container in log_failed_containers]) + + if len(containers_list) > 1: + archive_path = Path.cwd() / \ + "cloudphone_log_{}".format( + datetime.utcnow().strftime("%Y%m%d%H%M%S")) + else: + archive_path = Path.cwd() / \ + "{}_log_{}".format( + containers_list[0].name, + datetime.utcnow().strftime("%Y%m%d%H%M%S")) + + make_archive(str(archive_path), "gztar", str(self.log_path)) + + print("===log finished===") + rmtree(str(self.log_path)) + + def _resource_one_container(self, container): + container.reload() + if container.status != 'running': + print("container[short_id:{}, name:{}] is {}".format( + container.short_id, container.name, container.status)) + return False + + container_res = self.guestos_log_path / container.name + container_res.mkdir(parents=True, exist_ok=True) + + temp_log_path = "/data/" + self.log_path.parts[-1] + ret_val = self._run_cmd(container, "mkdir -p " + temp_log_path) \ + and self._run_cmd(container, "cp -r /proc/cpuinfo " + temp_log_path) \ + and self._run_cmd(container, "dumpsys meminfo", to_file=True) \ + and self._run_cmd(container, "top -n1", to_file=True) \ + and self._run_cmd(container, "df -h", to_file=True) \ + and self._run_cmd(container, "lspci", to_file=True) + + src_path = self._get_data_mount_path(container) + "/" + self.log_path.parts[-1] + dst_path = str(container_res / "data") + copytree(src_path, dst_path) + + return ret_val and self._run_cmd(container, "rm -rf " + temp_log_path) + + def resource_containers(self, containers): + admgpu_pm_info_pathes = Path( + "/sys/kernel/debug/dri/").glob('*/amdgpu_pm_info') + for src_path in admgpu_pm_info_pathes: + dst_path = self.hostos_log_path / \ + "amdgpu_pm_info_{}".format(src_path.parts[-2]) + copy(str(src_path), str(dst_path)) + + if containers: + containers_list = [self.__client.containers.get( + container) for container in containers] + else: + containers_list = self.__client.containers.list(all=True) + + if not containers_list: + logging.fatal("No container found") + return + + res_failed_containers = [] + for container in containers_list: + res_ok = self._resource_one_container(container) + if not res_ok: + res_failed_containers.append(container) + + print("===container resource report===\n") + print("Total containers: {}\n".format(len(containers_list))) + if res_failed_containers: + print("resource failed containers name:") + print([container.name for container in res_failed_containers]) + + if len(containers_list) > 1: + archive_path = Path.cwd() / \ + "cloudphone_res_{}".format( + datetime.utcnow().strftime("%Y%m%d%H%M%S")) + else: + archive_path = Path.cwd() / \ + "{}_res_{}".format( + containers_list[0].name, + datetime.utcnow().strftime("%Y%m%d%H%M%S")) + + make_archive(str(archive_path), "gztar", str(self.log_path)) + + print("===resource stats finished===") + rmtree(str(self.log_path)) \ No newline at end of file diff --git a/deploy_scripts/kbox_maintainer/readme.md b/deploy_scripts/kbox_maintainer/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..e69d5d7234ca20a9188bd2785ebcb26d3e234a10 --- /dev/null +++ b/deploy_scripts/kbox_maintainer/readme.md @@ -0,0 +1,16 @@ +# Kbox_Maintainer: A tool collection for Kbox maintainment + +# Requirements +- This tool must be put in deploy_scripts dir +- run `pip install -r requirements.txt` to install requirements before first run. + + +# Usage +This tool is written in Python3. +```shell +cd ./deploy_scripts +python3 kbox_maintainer.py --help +``` + + + diff --git a/deploy_scripts/kbox_maintainer/requirements.txt b/deploy_scripts/kbox_maintainer/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..b8076545056b8fb4c7b8969eed406e5c2907aefa --- /dev/null +++ b/deploy_scripts/kbox_maintainer/requirements.txt @@ -0,0 +1,4 @@ +docker==5.0.0 +py-cpuinfo==8.0.0 +requests==2.22.0 +six==1.16.0 \ No newline at end of file diff --git a/deploy_scripts/make_image_aosp15.sh b/deploy_scripts/make_image_aosp15.sh new file mode 100644 index 0000000000000000000000000000000000000000..598b24a076a920dfb5b7c426609381acc558e3ff --- /dev/null +++ b/deploy_scripts/make_image_aosp15.sh @@ -0,0 +1,261 @@ +#!/bin/bash +# 本脚本将基于kbox基础云手机镜像(AOSP15版本)、商用二进制包和目标GPU的二进制驱动合并制作云手机镜像,方便用户使用 +# 操作命令 +# ./make_image_aosp15.sh [kbox基础云手机镜像名称] [目标GPU Kbox云手机镜像名称] [gpu驱动包名称] +# 脚本至少提供两个参数 +#第一个参数:kbox基础云手机镜像名称:kbox:latest +#第二个参数:目标GPU Kbox云手机镜像名称:kbox:latest_{GPU_NAME} +#第三个参数:[gpu驱动包名称] 为可选参数,无该参数时默认制作基于amd GPU 的kbox镜像。 +# 例: +# ./make_image_aosp15.sh kbox:latest kbox:latest_ +# ./make_image_aosp15.sh kbox:latest kbox:latest_ xxxx.tar.gz + +set -e + +CUR_PATH=$(cd $(dirname "${0}");pwd) + +GPUTYPE="" +GPU_DRIVER_PACKAGE= +TMP_PACKAGE_DIR=${CUR_PATH}/imageFile +DOCKER_FILE_DIR=${CUR_PATH}/Dockerfiles +DOCKER_FILE_BAK=${CUR_PATH}/Dockerfile.bak +DOCKER_FILE=${CUR_PATH}/Dockerfile + +function gen_docker_file() +{ + local target_docker_file="${DOCKER_FILE_DIR}/Dockerfile_" + if [ ${GPUTYPE} = "amd" ]; then + target_docker_file="${target_docker_file}amd" + elif [ ${GPUTYPE} = "awm" ]; then + target_docker_file="${target_docker_file}awm" + elif [ ${GPUTYPE} = "va" ]; then + target_docker_file="${target_docker_file}va_aosp15" + fi + + # 判断Dockerfile是否存在 + if [ ! -f "${target_docker_file}" ]; then + echo -e "\033[1;31m[ERROR] ${target_docker_file} is not exist. \033[0m" && return -1 + fi + + if [ -f "${DOCKER_FILE}" ]; then + mv ${DOCKER_FILE} ${DOCKER_FILE_BAK} + fi + + cp ${target_docker_file} ${DOCKER_FILE} +} + +function gen_vagpu_package() +{ + cp -rp ${TMP_PACKAGE_DIR}/va_driver/system/* ${TMP_PACKAGE_DIR}/system/ + rm -rf ${TMP_PACKAGE_DIR}/system/vendor/bin/displayServer +} + +function gen_awmgpu_package() +{ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/codec_api/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/codec_api/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/codec_api/firmware/release/* ${TMP_PACKAGE_DIR}/system/etc/firmware/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm/libEGL_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm64/libEGL_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm/libIMGegl.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm64/libIMGegl.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm/libpvrANDROID_WSEGL.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm64/libpvrANDROID_WSEGL.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libGLESv1_CM_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libGLESv1_CM_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libGLESv2_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libGLESv2_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libsrv_um.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libsrv_um.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libufwriter.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libufwriter.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libusc.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libusc.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/firmware/* ${TMP_PACKAGE_DIR}/system/etc/firmware/awmgpu/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/gralloc/arm/* ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/gralloc/arm64/* ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/ifbc/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/ifbc/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/isr/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/isr/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/isr/wbc/ ${TMP_PACKAGE_DIR}/system/etc/firmware/awmgpu/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/libva/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/libva/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/va-api/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/va-api/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/openmax/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/openmax/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/vulkan/arm/* ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/vulkan/arm64/* ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/c-utils/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/c-utils/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ +} + +function prepare_gpu_driver() +{ + # 判断Dockerfile是否存在 + if [ ! -d "${DOCKER_FILE_DIR}" ]; then + echo -e "\033[1;31m[ERROR] ${DOCKER_FILE_DIR} is not exist. \033[0m" && return -1 + fi + + if [ ${GPUTYPE} != "amd" ]; then + # 解压GPU驱动包(注意:通过--no-same-owner保证解压后的文件属组为当前操作用户(root)文件属组) + cmd="tar --no-same-owner -zxvf ${GPU_DRIVER_PACKAGE} -C ${TMP_PACKAGE_DIR}" + echo -e "\033[1;36m[INFO] "$cmd" \033[0m" + $cmd > /dev/null + fi + + if [ $GPUTYPE == "awm" ]; then + gen_awmgpu_package + elif [ $GPUTYPE == "va" ]; then + gen_vagpu_package + fi + + gen_docker_file +} + +# 当前目录下有商用二进制压缩包时,使用该压缩包;如不存在该压缩包,跳过该步骤。避免覆盖用户自己编译镜像中的二进制。 +function prepare_kbox_binary() +{ + if [ -z $(ls | grep BoostKit-kbox_*.zip) ];then + echo -e -n "\033[1;31m[INFO] kbox binary package is not exist, " + echo -e "make sure ${DOCKER_IMAGE_IN} contain kbox binary. \033[0m" && return 0 + fi + BoostKit_package=$(ls BoostKit-kbox_*.zip) + unzip -o "${BoostKit_package}" -d ${TMP_PACKAGE_DIR} > /dev/null + binary_packages=$(ls ${TMP_PACKAGE_DIR}/Kbox-*-*-binary.zip) + unzip -o "${binary_packages}" -d ${TMP_PACKAGE_DIR} > /dev/null + BinaryPath=${TMP_PACKAGE_DIR}/product_prebuilt + + cp ${BinaryPath}/audio/lib/hw/audio.primary.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/audio/lib64/hw/audio.primary.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + cp ${BinaryPath}/gbm_gralloc/lib/hw/gralloc.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/gbm_gralloc/lib64/hw/gralloc.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + cp ${BinaryPath}/gps/lib/hw/gps.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/gps/lib64/hw/gps.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + + cp ${BinaryPath}/omx/lib/* ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp ${BinaryPath}/omx/lib64/* ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + + if [ $GPUTYPE = "awm" ]; then + cp ${BinaryPath}/product_hwcomposer/lib/hw/hwcomposer.awmgpu.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/product_hwcomposer/lib64/hw/hwcomposer.awmgpu.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + elif [ $GPUTYPE = "amd" ]; then + cp ${BinaryPath}/product_hwcomposer/lib/hw/hwcomposer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/product_hwcomposer/lib64/hw/hwcomposer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + fi + + cp ${BinaryPath}/sensors/lib/hw/sensors.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/sensors/lib64/hw/sensors.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + cp ${BinaryPath}/vinput/bin/vinput ${TMP_PACKAGE_DIR}/system/vendor/bin/ + cp ${BinaryPath}/vinput/vinput.rc ${TMP_PACKAGE_DIR}/system/vendor/etc/init/vinput.rc + + if [ -d ${BinaryPath}/RenderAccLayer ]; then + cp ${BinaryPath}/RenderAccLayer/lib/hw/RenderAccLayer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/RenderAccLayer/lib64/hw/RenderAccLayer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + cp ${BinaryPath}/RenderAccLayer/kbox_render_accelerating_configuration.xml ${TMP_PACKAGE_DIR}/system/vendor/etc/ + fi +} + +function prepare_file_system() +{ + # 判断目录是否存在,若存在则删除重建 + if [ -d "${TMP_PACKAGE_DIR}" ]; then + rm -rf ${TMP_PACKAGE_DIR} + fi + mkdir -p ${TMP_PACKAGE_DIR}/system/lib/hw + mkdir -p ${TMP_PACKAGE_DIR}/system/lib64/hw + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/bin/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/etc/init/ + if [ $GPUTYPE = "awm" ]; then + mkdir -p ${TMP_PACKAGE_DIR}/system/etc/firmware/awmgpu/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + fi +} + +function detect_gpu_type() +{ + XD_GPU_ID="1fe0:1010" + VA_GPU_ID=":0200" + local xd_gpus=($(lspci -D | grep ${XD_GPU_ID} | awk '{print $1}')) + local va_gpus=($(lspci -D | grep ${VA_GPU_ID} | awk '{print $1}')) + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + + if [ 0 -ne ${#amd_gpus[@]} ]; then + GPUTYPE="amd" + if [ "${GPU_DRIVER_PACKAGE}" != "" ]; then + echo -e "\033[1;31m[INFO] amd gpu doesn't need driver package, ignore: ${GPU_DRIVER_PACKAGE}. \033[0m" + return 0 + fi + elif [ 0 -ne ${#va_gpus[@]} ]; then + GPUTYPE="va" + if [ "${GPU_DRIVER_PACKAGE}" != "va"* ] || [ -z $(ls | grep "${GPU_DRIVER_PACKAGE}") ]; then + echo -e -n "\033[1;31m[ERROR] please check gpu driver package " + echo -e "and make sure it match the gpu type. \033[0m" && exit -1 + fi + elif [ 0 -ne ${#xd_gpus[@]} ]; then + GPUTYPE="awm" + if [ "${GPU_DRIVER_PACKAGE}" != "awmgpu"* ] || [ -z $(ls | grep "${GPU_DRIVER_PACKAGE}") ]; then + echo -e -n "\033[1;31m[ERROR] please check gpu driver package " + echo -e "and make sure it match the gpu type. \033[0m" && exit -1 + fi + else + echo -e "\033[1;31m[ERROR] unsupport gpu type. \033[0m" && exit -1 + fi +} + +# 制作镜像 +function make_image() +{ + cmd="docker build --build-arg KBOX_IMAGE=${DOCKER_IMAGE_IN} -t ${DOCKER_IMAGE_OUT} ." + echo -e "\033[1;36m[INFO] "$cmd" \033[0m" + $cmd + wait +} + +function main() +{ + echo -e "\033[1;36m[INFO] Begin to make image \033[0m" + local start_time=$(date +%s) + local end_time=0 + + if [ $# -ne 2 ] && [ $# -ne 3 ]; then + echo -e "\033[1;31m[ERROR] input args should include base image, image to be made and gpu driver package\033[0m" + exit -1; + fi + + DOCKER_IMAGE_IN="$1" + DOCKER_IMAGE_OUT="$2" + + if [ -n "$3" ]; then + GPU_DRIVER_PACKAGE=$3 + fi + + detect_gpu_type + prepare_file_system + prepare_kbox_binary + prepare_gpu_driver + + make_image + [ ${?} != 0 ] && echo -e "\033[1;31m[ERROR] Failed to make image. \033[0m" && exit -1 + + # 制作镜像时间统计 + end_time=$(date +%s) + time_interval=$((${end_time}-${start_time})) + echo -e "\033[1;36m[INFO] End to make image from ${DOCKER_IMAGE_IN} to ${DOCKER_IMAGE_OUT} \033[0m" + echo -e "\033[1;36m[INFO] Make image takes ${time_interval} seconds. \033[0m" +} + +main "$@" diff --git a/deploy_scripts/openEuler_deploy/kbox_install_kernel.sh b/deploy_scripts/openEuler_deploy/kbox_install_kernel.sh new file mode 100644 index 0000000000000000000000000000000000000000..555c7a0a8a2ad6e56c5163bcbb68b5b4335556bd --- /dev/null +++ b/deploy_scripts/openEuler_deploy/kbox_install_kernel.sh @@ -0,0 +1,387 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2023-2023. All rights reserved. +# File Name: kbox_install_kernel.sh +# Description: openEuler kbox内核编译安装及环境部署。 +# Usage: +# 1.请确认脚本位于:Kbox-AOSP*/deploy_scripts/openEuler_deploy/ +# 2.需使用root用户或sudo命令执行此脚本 +# 3.脚本运行格式: +# [1] 联网模式:该模式下脚本会联网下载所需源码包 +# ./kbox_install_kernel.sh +# [2] 本地模式:该模式下脚本会会从本地获取源码包,${packages_dir}即本地包所在目录的绝对路径,详见步骤4 +# ./kbox_install_kernel.sh ${packages_dir} +# 示例: ./kbox_install_kernel.sh /home/kbox_packages/ +# 4.若使用"本地模式"运行脚本,需提前上传以下文件到${packages_dir}目录下:("联网模式"无需上传) +# [1] linux-firmware-20210919.tar.gz (仅amdgpu需要) +# [2] kernel-5.10.0-136.12.0.zip 或 kernel-5.10.0-182.0.0.zip 或 kernel-5.10.0-216.0.0.zip +# [3] ExaGear_ARM32-ARM64_V2.5.tar.gz +# ******************************************************************************** # + +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ] +then + bash "$0" "$@" + exit $? +fi + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +# 操作系统版本 +OS_MAJOR_VERSION="openEuler_22.03" +OS_MINOR_VERSION=$(cat /etc/os-release | grep -w VERSION | awk -F '[" ]' '{print $3}' | sed 's/(//g' | sed 's/)//g') +# linux kernel版本 +if [ ${OS_MINOR_VERSION} = "LTS-SP1" ] +then + KERNEL_VERSION="5.10.0-136.12.0" +elif [ ${OS_MINOR_VERSION} = "LTS-SP3" ] +then + KERNEL_VERSION="5.10.0-182.0.0" +else + KERNEL_VERSION="5.10.0-216.0.0" +fi + +exagear_bin_src="https://kunpeng-repo.obs.cn-north-4.myhuaweicloud.com/Exagear ARM32-ARM64/Exagear ARM32-ARM64 202.0.0/ExaGear_ARM32-ARM64_V2.5.tar.gz" +linux_firmware_src="https://mirrors.edge.kernel.org/pub/linux/kernel/firmware/linux-firmware-20210919.tar.gz" +linux_firmware_verify_src="https://mirrors.edge.kernel.org/pub/linux/kernel/firmware/sha256sums.asc" +kernel_src="https://gitee.com/openeuler/kernel.git" + +# 内核源码存放目录 +kernel_dir="/usr/src/kernels/" +# 当前目录 +CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +cd "${CURRENT_DIR}" || exit +# 依赖目录 +mkdir -p /root/dependency/ +work_dir=/root/dependency/ +# Kbox_AOSP根目录 +kbox_dir=$(cd "${CURRENT_DIR}"/../../ && pwd) +# 本地依赖包目录 +packages_dir=$1 + +cpu_num=$(< /proc/cpuinfo grep -c "processor") + +################################################################################ +# Function Name: check_local_package +# Description : 检查本地依赖包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function check_local_package(){ + [ -e "${packages_dir}/${1}" ] || error "指定路径下无法找到${packages_dir}/${1}" +} + +################################################################################ +# Function Name: check_local_packages +# Description : 检查本地依赖包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function check_local_packages(){ + # 仅amdgpu需准备固件包 + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + if [ 0 -ne ${#amd_gpus[@]} ]; then + check_local_package "linux-firmware-20210919.tar.gz" + fi + check_local_package "kernel-${KERNEL_VERSION}.zip" + check_local_package "ExaGear_ARM32-ARM64_V2.5.tar.gz" +} + +################################################################################ +# Function Name: set_run_mode +# Description : 选择源码包获取方式 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function set_run_mode(){ + if [ $# -eq 0 ] + then + run_mode="Download" + elif [ $# -eq 1 ] + then + run_mode="Local" + else + error "The number of input parameters is incorrect." + fi +} + +################################################################################ +# Function Name: modify_config +# Description : config文件修改。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function modify_config(){ + < ${3} grep -v "#"|grep -w "${1}" + if [ $? -eq 0 ] + then + if [ "${2}" = "n" ] + then + sed -i "s|${1}=.*|\# ${1} is not set|g" ${3} + else + sed -i "s|${1}=.*|${1}=${2}|g" ${3} + fi + else + if [ "${2}" != "n" ] + then + echo "${1}=${2}" >> ${3} + fi + fi + echo "${3} >> $(< ${3} grep -w "${1}")" +} + +################################################################################ +# Function Name: install_dependency +# Description : 安装编译构建所需依赖。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_dependency(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 1 安装依赖 ]]]]]]]]]]]]]]]]]]]]" + yum install -y dpkg dpkg-devel openssl openssl-devel ncurses ncurses-devel \ + bison flex bc libdrm build elfutils-libelf-devel docker lxc \ + lxcfs lxcfs-tools git tar patch make gcc + systemctl start lxcfs + systemctl enable lxcfs +} + +################################################################################ +# Function Name: download_copy_packages +# Description : 下载/拷贝源码包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function download_copy_packages(){ + local verify_sha256sums + local file_sha256sums + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + cd "${work_dir}" || exit + if [ ${run_mode} = "Download" ] + then + echo "[[[[[[[[[[[[[[[[[[[[ STEP 2 源码包下载 ]]]]]]]]]]]]]]]]]]]]" + + # 仅amdgpu需下载固件包 + if [ 0 -ne ${#amd_gpus[@]} ]; then + local verify_sha256sums="" + local file_sha256sums="" + [ -e "sha256sums.asc" ] && rm -rf sha256sums.asc + echo "---------校验linux固件---------" + wget -q --show-progress ${linux_firmware_verify_src} --no-check-certificate || error "固件校验文件下载失败" + verify_sha256sums=$(grep linux-firmware-20210919.tar.gz sha256sums.asc) + [ -e "linux-firmware-20210919.tar.gz" ] && file_sha256sums=$(sha256sum linux-firmware-20210919.tar.gz) + if [ "${verify_sha256sums}" != "${file_sha256sums}" ] + then + [ -e "linux-firmware-20210919.tar.gz" ] && rm -rf linux-firmware-20210919.tar.gz + echo "---------下载linux固件---------" + wget -q --show-progress "${linux_firmware_src}" --no-check-certificate || error "固件下载失败" + fi + fi + + echo "---------下载kernel源码---------" + [ -e "${kernel_dir}/kernel-${KERNEL_VERSION}" ] && rm -rf "${kernel_dir}/kernel-${KERNEL_VERSION}" + git config --global http.sslVerify false + git clone -b ${KERNEL_VERSION} --depth 1 ${kernel_src} "${kernel_dir}/kernel-${KERNEL_VERSION}" || error "kernel源码下载失败" + + echo "---------下载Exagear二进制---------" + [ -e "ExaGear_ARM32-ARM64_V2.5.tar.gz" ] && rm -rf ExaGear_ARM32-ARM64_V2.5.tar.gz + wget -q --show-progress "${exagear_bin_src}" --no-check-certificate || error "Exagear二进制下载失败" + else + echo "[[[[[[[[[[[[[[[[[[[[ STEP 2 源码包准备 ]]]]]]]]]]]]]]]]]]]]" + check_local_packages + cp "${packages_dir}/ExaGear_ARM32-ARM64_V2.5.tar.gz" . || exit + + if [ 0 -ne ${#amd_gpus[@]} ]; then + cp "${packages_dir}/linux-firmware-20210919.tar.gz" . || exit + fi + cp "${packages_dir}/kernel-${KERNEL_VERSION}.zip" "${kernel_dir}" || exit + [ -e "${kernel_dir}/kernel-${KERNEL_VERSION}" ] && rm -rf "${kernel_dir}/kernel-${KERNEL_VERSION}" + unzip "${kernel_dir}/kernel-${KERNEL_VERSION}.zip" -d "${kernel_dir}" > /dev/null 2>&1 || error "kernel-${KERNEL_VERSION}.zip解压失败" + fi +} + +################################################################################ +# Function Name: enable_exagear +# Description : 转码使能。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function enable_exagear(){ + cd ${work_dir} || exit + + local UBT_PATHS=($(ls ${work_dir}/*/ubt_a32a64 | sed 's/ubt_a32a64//')) + for PA in ${UBT_PATHS[@]}; do + rm -rf "${PA}" + done + + tar -xzvf ExaGear_ARM32-ARM64_V2.5.tar.gz > /dev/null 2>&1 || error "ExaGear_ARM32-ARM64_V2.5.tar.gz解压失败" + local NEW_UBT_PATHS=$(ls ${work_dir}/*/ubt_a32a64 | sed 's/ubt_a32a64//') + chown -R root:root "${NEW_UBT_PATHS}" + chmod -R 700 "${NEW_UBT_PATHS}" + mkdir -p /opt/exagear + chmod -R 700 /opt/exagear + cp -f ${NEW_UBT_PATHS}/ubt_a32a64 /opt/exagear/ || exit + chmod +x /opt/exagear/ubt_a32a64 +} + +################################################################################ +# Function Name: prepare_environment +# Description : 环境准备。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function prepare_environment(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 3 环境准备 ]]]]]]]]]]]]]]]]]]]]" + echo "---------使能Exagear---------" + enable_exagear + + # 仅amdgpu需更新固件 + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + if [ 0 -ne ${#amd_gpus[@]} ]; then + echo "---------更新gpu固件---------" + cd "${work_dir}" || exit + [ -e "linux-firmware-20210919" ] && rm -rf linux-firmware-20210919 + tar -xvpf linux-firmware-20210919.tar.gz > /dev/null 2>&1 || error "linux-firmware-20210919.tar.gz解压失败" + cp -ar linux-firmware-20210919/*gpu /usr/lib/firmware/ || exit + echo "---------gpu固件更新完毕" + fi + + echo "---------文件配置---------" + modify_config "fs.inotify.max_user_instances" "8192" /etc/sysctl.conf + if [ ! -e "/etc/selinux/config" ] + then + touch /etc/selinux/config + echo "SELINUX=disabled" >> /etc/selinux/config + else + modify_config "SELINUX" "disabled" /etc/selinux/config + fi + echo "---------以上配置在重启后生效---------" +} + +################################################################################ +# Function Name: apply_patch +# Description : 转码及内核补丁合入。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function apply_patch(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 4 合入kernel补丁 ]]]]]]]]]]]]]]]]]]]]" + touch ${kernel_dir}/kernel-${KERNEL_VERSION}/.scmversion + + cd "${kbox_dir}"/patchForExagear/hostOS || exit + cp 0001-exagear-kernel-module.patch "${kernel_dir}"/kernel-"${KERNEL_VERSION}"/ || exit + cd "${kbox_dir}"/patchForKernel/"${OS_MAJOR_VERSION}"/kernel_"${KERNEL_VERSION}"/ || exit + cp *.patch "${kernel_dir}"/kernel-"${KERNEL_VERSION}" || exit + + cd "${kernel_dir}"/kernel-"${KERNEL_VERSION}"/ || exit + exagear_patch_name=$(ls | grep .patch | grep -m 1 module) + echo "-- patching ${exagear_patch_name}" + patch -p1 < ${exagear_patch_name} || exit + patches_list=$(ls | grep -v module | grep .patch) + for patch_name in ${patches_list[@]} + do + echo "-- patching ${patch_name}" + patch -p1 < ${patch_name} || exit + done +} + +################################################################################ +# Function Name: build_install_kernel +# Description : 内核及内核模块编译。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function build_install_kernel(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 5 编译&安装kernel ]]]]]]]]]]]]]]]]]]]]" + echo "---------内核编译---------" + cd "${kernel_dir}"/kernel-"${KERNEL_VERSION}"/ || exit + if [ -e /boot/config-$(uname -r) ]; then + cp /boot/config-$(uname -r) .config || exit + else + cp /boot/$(ls /boot/ | grep -m1 config-) .config || exit + fi + + (echo -e \'\\0x65\'; echo -e \'\\0x79\') | make menuconfig > /dev/null 2>&1 + sleep 1 + + [ ! -e ".config" ] && error "config file not found" + modify_config "CONFIG_KBOX" "y" .config + modify_config "CONFIG_ANDROID_BINDER_DEVICES" "\"binder,hwbinder,vndbinder\"" .config + modify_config "CONFIG_HISI_PMU" "m" .config + modify_config "CONFIG_SYSTEM_TRUSTED_KEYS" "\"\"" .config + modify_config "CONFIG_DEBUG_INFO" "n" .config + modify_config "CONFIG_PID_RESERVE" "n" .config + modify_config "CONFIG_PSI_DEFAULT_DISABLED" "n" .config + modify_config "CONFIG_LOCALVERSION" "\"\"" .config + modify_config "CONFIG_SYSTEM_REVOCATION_KEYS" "\"\"" .config + + (echo -e \'\\0x65\'; echo -e \'\\0x79\') | make menuconfig > /dev/null 2>&1 + sleep 1 + + echo "---------内核编译---------" + make clean && make -j"${cpu_num}" + [ $? -ne 0 ] && error "内核编译失败" + echo "---------安装模块---------" + make modules_install + [ $? -ne 0 ] && error "模块安装失败" + echo "---------安装内核---------" + yum list installed | grep dkms > /dev/null 2>&1 + [ $? -eq 0 ] && yum remove -y dkms > /dev/null 2>&1 # dkms会导致make install报错 + make install + make install # 重复运行一遍,以消除uds、kvdo相关报错 + [ $? -ne 0 ] && error "内核安装失败" + echo "---------更新启动项---------" + local grub_cmdline=$(grep -Po 'GRUB_CMDLINE_LINUX="\K.*(?=")' /etc/default/grub | tr -s ' ') + local check_cmdline=""cgroup_enable=memory" "swapaccount=1"" + if [[ -z "$grub_cmdline" ]]; then + sed -i "s/GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX=\"cgroup_enable=memory swapaccount=1\"/g" /etc/default/grub + else + for p in ${check_cmdline[@]}; do + if [[ ! "$grub_cmdline" =~ "$p" ]]; then + grub_cmdline="$grub_cmdline $p" + fi + done + sed -i "s#^GRUB_CMDLINE_LINUX=.*#GRUB_CMDLINE_LINUX=\"$grub_cmdline\"#g" /etc/default/grub + fi + sed -i "s/GRUB_DEFAULT=.*/GRUB_DEFAULT=saved/g" /etc/default/grub + grub2-mkconfig -o /boot/efi/EFI/openEuler/grub.cfg + grub_default=$(< /boot/efi/EFI/openEuler/grub.cfg grep "menuentry"|grep -v "recovery mode\|old"|grep -w "(5.10.0)"|awk -F \' '{print $2}') + grub2-set-default "${grub_default}" + [ $? -ne 0 ] && error "启动项更新失败" +} + +################################################################################ +# Function Name: system_reboot +# Description : 系统重启。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function system_reboot(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 6 重启系统 ]]]]]]]]]]]]]]]]]]]]" + local reboot_val + read -p "内核安装与参数配置已完成, 是否重启以生效 [Y/y]" reboot_val + + if [ ${reboot_val} = "Y" ] || [ ${reboot_val} = "y" ] + then + echo "---------系统即将重启---------" + reboot + else + echo "---------请稍后手动重启系统---------" + fi +} + +main(){ + set_run_mode $@ + install_dependency + download_copy_packages + prepare_environment + apply_patch + build_install_kernel + system_reboot +} + +main "$@" +exit 0 diff --git a/deploy_scripts/ubuntu_deploy/kbox_install_kernel.sh b/deploy_scripts/ubuntu_deploy/kbox_install_kernel.sh new file mode 100644 index 0000000000000000000000000000000000000000..7bf51094af5577aa5a8ed22d2fe7105f5d55bd53 --- /dev/null +++ b/deploy_scripts/ubuntu_deploy/kbox_install_kernel.sh @@ -0,0 +1,444 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2023-2023. All rights reserved. +# File Name: kbox_install_kernel.sh +# Description: ubuntu kbox内核编译安装及环境部署。 +# Usage: +# 1.请确认脚本位于:Kbox-AOSP*/deploy_scripts/ubuntu_deploy/ +# 2.需使用root用户或sudo命令执行此脚本 +# 3.脚本运行格式: +# [1] 联网模式:该模式下脚本会联网下载所需源码包 +# ./kbox_install_kernel.sh +# [2] 本地模式:该模式下脚本会会从本地获取源码包,${packages_dir}即本地包所在目录的绝对路径,详见步骤4 +# ./kbox_install_kernel.sh ${packages_dir} +# 示例: ./kbox_install_kernel.sh /home/kbox_packages/ +# 4.若使用"本地模式"运行脚本,需提前上传以下文件到${packages_dir}目录下:("联网模式"无需上传) +# [1] linux-firmware-20210919.tar.gz (仅amdgpu需要) +# [2] linux-5.15.98.tar.gz +# [3] docker-19.03.15.tgz +# [4] ExaGear_ARM32-ARM64_V2.5.tar.gz +# ******************************************************************************** # + +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ] +then + bash "$0" "$@" + exit $? +fi + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +# 操作系统版本 +OS_VERSION="ubuntu_20.04" +# linux kernel版本 +KERNEL_VERSION="5.15.98" + +docker_src="https://download.docker.com/linux/static/stable/aarch64/docker-19.03.15.tgz" +exagear_bin_src="https://kunpeng-repo.obs.cn-north-4.myhuaweicloud.com/Exagear ARM32-ARM64/Exagear ARM32-ARM64 202.0.0/ExaGear_ARM32-ARM64_V2.5.tar.gz" +linux_firmware_src="https://mirrors.edge.kernel.org/pub/linux/kernel/firmware/linux-firmware-20210919.tar.gz" +linux_firmware_verify_src="https://mirrors.edge.kernel.org/pub/linux/kernel/firmware/sha256sums.asc" +kernel_src="https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-${KERNEL_VERSION}.tar.gz" +kernel_verify_src="https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/sha256sums.asc" + +# 内核源码存放目录 +kernel_dir="/usr/src/" +# 当前目录 +CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +cd "${CURRENT_DIR}" || exit +# 依赖目录 +mkdir -p /root/dependency/ +work_dir=/root/dependency/ +# Kbox_AOSP根目录 +kbox_dir=$(cd "${CURRENT_DIR}"/../../ && pwd) +# 本地依赖包目录 +packages_dir=$1 + +cpu_num=$(< /proc/cpuinfo grep -c "processor") + +################################################################################ +# Function Name: check_local_package +# Description : 检查本地依赖包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function check_local_package(){ + [ -e "${packages_dir}/${1}" ] || error "指定路径下无法找到${packages_dir}/${1}" +} + +################################################################################ +# Function Name: check_local_packages +# Description : 检查本地依赖包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function check_local_packages(){ + # 仅amdgpu需准备固件包 + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + if [ 0 -ne ${#amd_gpus[@]} ]; then + check_local_package "linux-firmware-20210919.tar.gz" + fi + check_local_package "linux-${KERNEL_VERSION}.tar.gz" + check_local_package "docker-19.03.15.tgz" + check_local_package "ExaGear_ARM32-ARM64_V2.5.tar.gz" +} + +################################################################################ +# Function Name: set_run_mode +# Description : 选择源码包获取方式 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function set_run_mode(){ + if [ $# -eq 0 ] + then + run_mode="Download" + elif [ $# -eq 1 ] + then + run_mode="Local" + else + error "The number of input parameters is incorrect." + fi +} + +################################################################################ +# Function Name: modify_config +# Description : config文件修改。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function modify_config(){ + < ${3} grep -v "#"|grep -w "${1}" + if [ $? -eq 0 ] + then + if [ "${2}" = "n" ] + then + sed -i "s|${1}=.*|\# ${1} is not set|g" ${3} + else + sed -i "s|${1}=.*|${1}=${2}|g" ${3} + fi + else + if [ "${2}" != "n" ] + then + echo "${1}=${2}" >> ${3} + fi + fi + echo "${3} >> $(< ${3} grep -w "${1}")" +} + +################################################################################ +# Function Name: download_copy_packages +# Description : 下载/拷贝源码包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function download_copy_packages(){ + local verify_sha256sums + local file_sha256sums + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + cd "${work_dir}" || exit + if [ ${run_mode} = "Download" ] + then + echo "[[[[[[[[[[[[[[[[[[[[ STEP 1 源码包下载 ]]]]]]]]]]]]]]]]]]]]" + + # 仅amdgpu需下载固件包 + if [ 0 -ne ${#amd_gpus[@]} ]; then + local verify_sha256sums="" + local file_sha256sums="" + [ -e "sha256sums.asc" ] && rm -rf sha256sums.asc + echo "---------校验linux固件---------" + wget -q --show-progress ${linux_firmware_verify_src} --no-check-certificate || error "固件校验文件下载失败" + verify_sha256sums=$(grep linux-firmware-20210919.tar.gz sha256sums.asc) + [ -e "linux-firmware-20210919.tar.gz" ] && file_sha256sums=$(sha256sum linux-firmware-20210919.tar.gz) + if [ "${verify_sha256sums}" != "${file_sha256sums}" ] + then + [ -e "linux-firmware-20210919.tar.gz" ] && rm -rf linux-firmware-20210919.tar.gz + echo "---------下载linux固件---------" + wget -q --show-progress "${linux_firmware_src}" --no-check-certificate || error "固件下载失败" + fi + fi + + verify_sha256sums="" + file_sha256sums="" + [ -e "sha256sums.asc" ] && rm -rf sha256sums.asc + echo "---------校验kernel源码---------" + wget -q --show-progress ${kernel_verify_src} --no-check-certificate || error "kernel校验文件下载失败" + verify_sha256sums=$(grep linux-${KERNEL_VERSION}.tar.gz sha256sums.asc) + [ -e "linux-${KERNEL_VERSION}.tar.gz" ] && file_sha256sums=$(sha256sum linux-${KERNEL_VERSION}.tar.gz) + if [ "${verify_sha256sums}" != "${file_sha256sums}" ] + then + [ -e "linux-${KERNEL_VERSION}.tar.gz" ] && rm -rf linux-${KERNEL_VERSION}.tar.gz + echo "---------下载kernel源码---------" + wget -q --show-progress "${kernel_src}" --no-check-certificate || error "kernel源码下载失败" + fi + + echo "---------下载docker---------" + [ -e "docker-19.03.15.tgz" ] && rm -rf docker-19.03.15.tgz + wget -q --show-progress "${docker_src}" --no-check-certificate || error "docker下载失败" + + echo "---------下载Exagear二进制---------" + [ -e "ExaGear_ARM32-ARM64_V2.5.tar.gz" ] && rm -rf ExaGear_ARM32-ARM64_V2.5.tar.gz + wget -q --show-progress "${exagear_bin_src}" --no-check-certificate || error "Exagear二进制下载失败" + else + echo "[[[[[[[[[[[[[[[[[[[[ STEP 1 源码包准备 ]]]]]]]]]]]]]]]]]]]]" + check_local_packages + cp "${packages_dir}/docker-19.03.15.tgz" . || exit + cp "${packages_dir}/ExaGear_ARM32-ARM64_V2.5.tar.gz" . || exit + + if [ 0 -ne ${#amd_gpus[@]} ]; then + cp "${packages_dir}/linux-firmware-20210919.tar.gz" . || exit + fi + cp "${packages_dir}/linux-${KERNEL_VERSION}.tar.gz" . || exit + fi +} + +################################################################################ +# Function Name: install_dependency +# Description : 安装编译构建所需依赖。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_dependency(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 2 安装依赖 ]]]]]]]]]]]]]]]]]]]]" + apt update || exit + apt install -y dpkg dpkg-dev libncurses5-dev libssl-dev libpciaccess0 \ + libdrm-amdgpu1 xserver-xorg-video-amdgpu lxc build-essential \ + libncurses5-dev openssl libssl-dev pkg-config bison flex libelf-dev +} + +################################################################################ +# Function Name: install_docker +# Description : 安装预置的docker-*.tgz包。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_docker(){ + local docker_version=$(docker -v | grep "Docker version") + if [[ -n ${docker_version} ]] + then + echo "docker已安装" + return 0 + fi + + cd ${work_dir} || exit + [ -e "docker" ] && rm -rf docker + tar xvpf docker-19.03.15.tgz > /dev/null 2>&1 || error "docker-19.03.15.tgz解压失败" + cp -p docker/* /usr/bin || exit + cat >/usr/lib/systemd/system/docker.service < /dev/null 2>&1 || error "ExaGear_ARM32-ARM64_V2.5.tar.gz解压失败" + local NEW_UBT_PATHS=$(ls ${work_dir}/*/ubt_a32a64 | sed 's/ubt_a32a64//') + chown -R root:root "${NEW_UBT_PATHS}" + chmod -R 700 "${NEW_UBT_PATHS}" + mkdir -p /opt/exagear + chmod -R 700 /opt/exagear + cp -f ${NEW_UBT_PATHS}/ubt_a32a64 /opt/exagear/ || exit + chmod +x /opt/exagear/ubt_a32a64 +} + +################################################################################ +# Function Name: prepare_environment +# Description : 环境准备。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function prepare_environment(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 3 环境准备 ]]]]]]]]]]]]]]]]]]]]" + echo "---------安装docker---------" + install_docker + + echo "---------使能Exagear---------" + enable_exagear + + # 仅amdgpu需更新固件 + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + if [ 0 -ne ${#amd_gpus[@]} ]; then + echo "---------更新gpu固件---------" + cd "${work_dir}" || exit + [ -e "linux-firmware-20210919" ] && rm -rf linux-firmware-20210919 + tar -xvpf linux-firmware-20210919.tar.gz > /dev/null 2>&1 || error "linux-firmware-20210919.tar.gz解压失败" + cp -ar linux-firmware-20210919/*gpu /usr/lib/firmware/ || exit + echo "---------gpu固件更新完毕" + fi + + echo "---------文件配置---------" + modify_config "fs.inotify.max_user_instances" "8192" /etc/sysctl.conf + if [ ! -e "/etc/selinux/config" ] + then + touch /etc/selinux/config + echo "SELINUX=disabled" >> /etc/selinux/config + else + modify_config "SELINUX" "disabled" /etc/selinux/config + fi + echo "---------以上配置在重启后生效---------" +} + +################################################################################ +# Function Name: apply_patch +# Description : 转码及内核补丁合入。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function apply_patch(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 4 合入kernel补丁 ]]]]]]]]]]]]]]]]]]]]" + + cd "${work_dir}" || exit + [ -e "linux-${KERNEL_VERSION}" ] && rm -rf linux-${KERNEL_VERSION} + [ -e "linux-kernel-${KERNEL_VERSION}" ] && rm -rf linux-kernel-${KERNEL_VERSION} + echo "---------解压kernel源码---------" + tar -zxvf "linux-${KERNEL_VERSION}.tar.gz" > /dev/null 2>&1 || error "linux-${KERNEL_VERSION}.tar.gz解压失败" + mv linux-${KERNEL_VERSION} linux-kernel-${KERNEL_VERSION} + [ -e "${kernel_dir}/linux-kernel-${KERNEL_VERSION}" ] && rm -rf ${kernel_dir}/linux-kernel-${KERNEL_VERSION} + cp -r linux-kernel-${KERNEL_VERSION} ${kernel_dir} || exit + touch ${kernel_dir}/linux-kernel-${KERNEL_VERSION}/.scmversion + + cd "${kbox_dir}"/patchForExagear/hostOS/ || exit + cp 0001-exagear-kernel-module.patch "${kernel_dir}"/linux-kernel-"${KERNEL_VERSION}" || exit + + cd "${kbox_dir}"/patchForKernel/"${OS_VERSION}"/kernel_"${KERNEL_VERSION}"/ || exit + cp *.patch "${kernel_dir}"/linux-kernel-"${KERNEL_VERSION}" || exit + + cd "${kernel_dir}"/linux-kernel-"${KERNEL_VERSION}"/ || exit + exagear_patch_name=$(ls | grep .patch | grep -m 1 module) + echo "-- patching ${exagear_patch_name}" + patch -p1 < ${exagear_patch_name} || exit + patches_list=$(ls | grep -v module | grep .patch) + for patch_name in ${patches_list[@]} + do + echo "-- patching ${patch_name}" + patch -p1 < ${patch_name} || exit + done +} + +################################################################################ +# Function Name: build_install_kernel +# Description : 内核及内核模块编译。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function build_install_kernel(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 5 编译&安装kernel ]]]]]]]]]]]]]]]]]]]]" + echo "---------内核编译---------" + cd "${kernel_dir}"/linux-kernel-"${KERNEL_VERSION}"/ || exit + cp /boot/config-$(uname -r) .config || exit + + (echo -e \'\\0x65\'; echo -e \'\\0x79\') | make menuconfig > /dev/null 2>&1 + sleep 1 + + [ ! -e ".config" ] && error "config file not found" + modify_config "CONFIG_STAGING" "y" .config + modify_config "CONFIG_ANDROID" "y" .config + modify_config "CONFIG_ASHMEM" "y" .config + modify_config "CONFIG_ANDROID_BINDER_IPC" "y" .config + modify_config "CONFIG_ANDROID_BINDERFS" "y" .config + modify_config "CONFIG_ANDROID_ALARM" "y" .config + modify_config "CONFIG_ANON_VMA_NAME" "y" .config + modify_config "CONFIG_TANGO32" "y" .config + modify_config "CONFIG_VFAT_FS" "y" .config + modify_config "CONFIG_INPUT_UINPUT" "y" .config + modify_config "CONFIG_HISI_PMU" "y" .config + modify_config "CONFIG_SYSTEM_TRUSTED_KEYS" "\"\"" .config + modify_config "CONFIG_DEBUG_INFO" "n" .config + modify_config "CONFIG_LOCALVERSION" "\"\"" .config + modify_config "CONFIG_SYSTEM_REVOCATION_KEYS" "\"\"" .config + + (echo -e \'\\0x65\'; echo -e \'\\0x79\') | make menuconfig > /dev/null 2>&1 + sleep 1 + + echo "---------内核编译---------" + make clean && make -j"${cpu_num}" + [ $? -ne 0 ] && error "内核编译失败" + echo "---------安装模块---------" + make modules_install + [ $? -ne 0 ] && error "模块安装失败" + echo "---------安装内核---------" + make install + [ $? -ne 0 ] && error "内核安装失败" + echo "---------更新启动项---------" + grub_default=$(< /boot/grub/grub.cfg grep "Ubuntu, with Linux"|awk -F \' '{print i++ ":"$2}'|grep -v "recovery mode"|grep -w ""${KERNEL_VERSION}"$"|awk -F ':' '{print $1}') + sed -i "s/GRUB_DEFAULT=.*/GRUB_DEFAULT=\"1\> ${grub_default}\"/g" /etc/default/grub + sed -i "s/GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX=\"cgroup_enable=memory swapaccount=1\"/g" /etc/default/grub + update-grub2 + [ $? -ne 0 ] && error "启动项更新失败" +} + +################################################################################ +# Function Name: system_reboot +# Description : 系统重启。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function system_reboot(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 6 重启系统 ]]]]]]]]]]]]]]]]]]]]" + local reboot_val + read -p "内核安装与参数配置已完成, 是否重启以生效 [Y/y]" reboot_val + + if [ ${reboot_val} = "Y" ] || [ ${reboot_val} = "y" ] + then + echo "---------系统即将重启---------" + reboot + else + echo "---------请稍后手动重启系统---------" + fi +} + +main(){ + set_run_mode $@ + download_copy_packages + install_dependency + prepare_environment + apply_patch + build_install_kernel + system_reboot +} + +main "$@" +exit 0 diff --git a/apply-patch.sh b/patchForAndroid15/apply-patch.sh similarity index 100% rename from apply-patch.sh rename to patchForAndroid15/apply-patch.sh diff --git a/aosp15r17-patch/bionic/bionic-0001.patch b/patchForAndroid15/bionic/bionic-0001.patch similarity index 100% rename from aosp15r17-patch/bionic/bionic-0001.patch rename to patchForAndroid15/bionic/bionic-0001.patch diff --git a/aosp15r17-patch/device/google/cuttlefish/device-google-cuttlefish-0001.patch b/patchForAndroid15/device/google/cuttlefish/device-google-cuttlefish-0001.patch similarity index 100% rename from aosp15r17-patch/device/google/cuttlefish/device-google-cuttlefish-0001.patch rename to patchForAndroid15/device/google/cuttlefish/device-google-cuttlefish-0001.patch diff --git a/aosp15r17-patch/external/libdrm/external-libdrm-0001.patch b/patchForAndroid15/external/libdrm/external-libdrm-0001.patch similarity index 100% rename from aosp15r17-patch/external/libdrm/external-libdrm-0001.patch rename to patchForAndroid15/external/libdrm/external-libdrm-0001.patch diff --git a/aosp15r17-patch/external/libva/external-libva-0001.patch b/patchForAndroid15/external/libva/external-libva-0001.patch similarity index 100% rename from aosp15r17-patch/external/libva/external-libva-0001.patch rename to patchForAndroid15/external/libva/external-libva-0001.patch diff --git a/aosp15r17-patch/external/mesa3d/external-mesa3d-0001.patch b/patchForAndroid15/external/mesa3d/external-mesa3d-0001.patch similarity index 100% rename from aosp15r17-patch/external/mesa3d/external-mesa3d-0001.patch rename to patchForAndroid15/external/mesa3d/external-mesa3d-0001.patch diff --git a/aosp15r17-patch/external/mesa3d/external-mesa3d-0002-bug-fix.patch b/patchForAndroid15/external/mesa3d/external-mesa3d-0002-bug-fix.patch similarity index 100% rename from aosp15r17-patch/external/mesa3d/external-mesa3d-0002-bug-fix.patch rename to patchForAndroid15/external/mesa3d/external-mesa3d-0002-bug-fix.patch diff --git a/aosp15r17-patch/external/minigbm/external-minigbm-0001.patch b/patchForAndroid15/external/minigbm/external-minigbm-0001.patch similarity index 100% rename from aosp15r17-patch/external/minigbm/external-minigbm-0001.patch rename to patchForAndroid15/external/minigbm/external-minigbm-0001.patch diff --git a/aosp15r17-patch/external/minijail/external-minijail-0001.patch b/patchForAndroid15/external/minijail/external-minijail-0001.patch similarity index 100% rename from aosp15r17-patch/external/minijail/external-minijail-0001.patch rename to patchForAndroid15/external/minijail/external-minijail-0001.patch diff --git a/aosp15r17-patch/external/selinux/external-selinux-0001.patch b/patchForAndroid15/external/selinux/external-selinux-0001.patch similarity index 100% rename from aosp15r17-patch/external/selinux/external-selinux-0001.patch rename to patchForAndroid15/external/selinux/external-selinux-0001.patch diff --git a/aosp15r17-patch/frameworks/av/frameworks-av-0001.patch b/patchForAndroid15/frameworks/av/frameworks-av-0001.patch similarity index 100% rename from aosp15r17-patch/frameworks/av/frameworks-av-0001.patch rename to patchForAndroid15/frameworks/av/frameworks-av-0001.patch diff --git a/aosp15r17-patch/frameworks/base/frameworks-base-0001.patch b/patchForAndroid15/frameworks/base/frameworks-base-0001.patch similarity index 100% rename from aosp15r17-patch/frameworks/base/frameworks-base-0001.patch rename to patchForAndroid15/frameworks/base/frameworks-base-0001.patch diff --git a/aosp15r17-patch/frameworks/base/frameworks-base-0002.patch b/patchForAndroid15/frameworks/base/frameworks-base-0002.patch similarity index 100% rename from aosp15r17-patch/frameworks/base/frameworks-base-0002.patch rename to patchForAndroid15/frameworks/base/frameworks-base-0002.patch diff --git a/aosp15r17-patch/frameworks/native/frameworks-native-0001.patch b/patchForAndroid15/frameworks/native/frameworks-native-0001.patch similarity index 100% rename from aosp15r17-patch/frameworks/native/frameworks-native-0001.patch rename to patchForAndroid15/frameworks/native/frameworks-native-0001.patch diff --git a/aosp15r17-patch/hardware/libhardware/hardware-libhardware-0001.patch b/patchForAndroid15/hardware/libhardware/hardware-libhardware-0001.patch similarity index 100% rename from aosp15r17-patch/hardware/libhardware/hardware-libhardware-0001.patch rename to patchForAndroid15/hardware/libhardware/hardware-libhardware-0001.patch diff --git a/aosp15r17-patch/packages/modules/Bluetooth/packages-modules-Bluetooth-0001.patch b/patchForAndroid15/packages/modules/Bluetooth/packages-modules-Bluetooth-0001.patch similarity index 100% rename from aosp15r17-patch/packages/modules/Bluetooth/packages-modules-Bluetooth-0001.patch rename to patchForAndroid15/packages/modules/Bluetooth/packages-modules-Bluetooth-0001.patch diff --git a/aosp15r17-patch/packages/modules/Connectivity/packages-modules-Connectivity-0001.patch b/patchForAndroid15/packages/modules/Connectivity/packages-modules-Connectivity-0001.patch similarity index 100% rename from aosp15r17-patch/packages/modules/Connectivity/packages-modules-Connectivity-0001.patch rename to patchForAndroid15/packages/modules/Connectivity/packages-modules-Connectivity-0001.patch diff --git a/aosp15r17-patch/packages/modules/adb/packages-modules-adb-0001.patch b/patchForAndroid15/packages/modules/adb/packages-modules-adb-0001.patch similarity index 100% rename from aosp15r17-patch/packages/modules/adb/packages-modules-adb-0001.patch rename to patchForAndroid15/packages/modules/adb/packages-modules-adb-0001.patch diff --git a/reverse-patch.sh b/patchForAndroid15/reverse-patch.sh similarity index 100% rename from reverse-patch.sh rename to patchForAndroid15/reverse-patch.sh diff --git a/aosp15r17-patch/system/bpf/system-bpf-0001.patch b/patchForAndroid15/system/bpf/system-bpf-0001.patch similarity index 100% rename from aosp15r17-patch/system/bpf/system-bpf-0001.patch rename to patchForAndroid15/system/bpf/system-bpf-0001.patch diff --git a/aosp15r17-patch/system/core/system-core-0001.patch b/patchForAndroid15/system/core/system-core-0001.patch similarity index 100% rename from aosp15r17-patch/system/core/system-core-0001.patch rename to patchForAndroid15/system/core/system-core-0001.patch diff --git a/aosp15r17-patch/system/libbase/system-libbase-0001.patch b/patchForAndroid15/system/libbase/system-libbase-0001.patch similarity index 100% rename from aosp15r17-patch/system/libbase/system-libbase-0001.patch rename to patchForAndroid15/system/libbase/system-libbase-0001.patch diff --git a/aosp15r17-patch/system/libhwbinder/system-libhwbinder-0001.patch b/patchForAndroid15/system/libhwbinder/system-libhwbinder-0001.patch similarity index 100% rename from aosp15r17-patch/system/libhwbinder/system-libhwbinder-0001.patch rename to patchForAndroid15/system/libhwbinder/system-libhwbinder-0001.patch diff --git a/aosp15r17-patch/system/libvintf/system-libvintf-0001.patch b/patchForAndroid15/system/libvintf/system-libvintf-0001.patch similarity index 100% rename from aosp15r17-patch/system/libvintf/system-libvintf-0001.patch rename to patchForAndroid15/system/libvintf/system-libvintf-0001.patch diff --git a/aosp15r17-patch/system/netd/system-netd-0001.patch b/patchForAndroid15/system/netd/system-netd-0001.patch similarity index 100% rename from aosp15r17-patch/system/netd/system-netd-0001.patch rename to patchForAndroid15/system/netd/system-netd-0001.patch diff --git a/aosp15r17-patch/system/vold/system-vold-0001.patch b/patchForAndroid15/system/vold/system-vold-0001.patch similarity index 100% rename from aosp15r17-patch/system/vold/system-vold-0001.patch rename to patchForAndroid15/system/vold/system-vold-0001.patch