From: Adam Michalski Date: Mon, 18 Sep 2023 15:01:50 +0000 (+0200) Subject: Add isu status option X-Git-Tag: accepted/tizen/unified/20231101.174500~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c2633c2d341ad22f7899c52e5fdb4b6bea33c742;p=platform%2Fcore%2Fsystem%2Fisu.git Add isu status option Change-Id: I56b1c5c9b676d9a4da8685db35a4a92867516b80 --- diff --git a/packaging/isu.spec b/packaging/isu.spec index adbeab8..a0fff1d 100644 --- a/packaging/isu.spec +++ b/packaging/isu.spec @@ -1,6 +1,6 @@ Summary: Individual Service Upgrade support Name: isu -Version: 8.0.14 +Version: 8.0.15 Release: 1 Source0: %{name}-%{version}.tar.gz License: MIT diff --git a/src/pkg_manager/isu b/src/pkg_manager/isu index c6fbd56..d8aad73 100755 --- a/src/pkg_manager/isu +++ b/src/pkg_manager/isu @@ -4,6 +4,8 @@ set -u PATH=/bin:/usr/bin:/sbin:/usr/sbin ISU_PKGS_PATH=/opt/isu +ISU_RUN_PATH=/run/isu +ISU_CFGS_PATH=/etc/isu readonly PKG_FILE_NOT_EXIST=100 readonly PKG_INSTALL_ERROR=101 @@ -36,6 +38,20 @@ function print_install_help() echo " (for development purposes only)" } +function print_status_help() +{ + if [ -z "${1:-}" ]; then + echo "" + echo "Usage:" + echo -n " $0" + fi + + echo " status [-v] [] - show systemd service status. If no pkg_name given," + echo " show status for all isu services." + echo " -v - verbose mode: show sandboxing mechanism, mount files status etc." + echo " (output format subject to change, do not parse in scripts)" +} + function print_help() { echo "" @@ -46,6 +62,7 @@ function print_help() echo echo "commands:" echo " list - list installed packages" + print_status_help x print_install_help x print_remove_help x } @@ -63,6 +80,220 @@ function list_pkgs() done } +function query_systemd_mount_files() +{ + local mount_files=$(compgen -G "$ISU_PKGS_PATH/$pkg_name/system-services/*.mount" 2>/dev/null) + if [ -z "$mount_files" ]; then + is_systemd_mount_file_sandboxing=0 + return + fi + # there may be more than one mount file - check all of them, but only in verbose mode + if [ "$verbose" == 1 ]; then + for m_f in $mount_files; do + mount_file_name=$(basename "$m_f") + local detailed_mount_state=$(systemctl status "$mount_file_name" 2>&1) + grep -q 'Active: active (mounted)' <<< "$detailed_mount_state" || { + all_mounts_successful=0 + break + } + done + fi +} + +function show_sandboxing_method() +{ + local no_sandboxing=0 + if [ "$is_isu_sandboxed" == "0" ] && [ "$is_systemd_mount_file_sandboxing" == "0" ] && [ "$is_systemd_bind_paths" == "0" ]; then + no_sandboxing=1 + fi + + sandboxing_method="" + echo -n "sandboxing: " + if [ "$is_isu_sandboxed" == "1" ]; then + sandboxing_method+="isu-sandbox," + fi + if [ "$is_systemd_mount_file_sandboxing" == "1" ]; then + if [ "$all_mounts_successful" == "1" ]; then + sandboxing_method+="systemd mount files," + else + sandboxing_method+="systemd mount files [WARNING: not all mount files active]," + fi + fi + if [ "$is_systemd_bind_paths" == "1" ]; then + sandboxing_method+="systemd BindPaths/TemporaryFileSystem" + fi + if [ "$no_sandboxing" == "1" ]; then + sandboxing_method+="no sandboxing" + fi + + echo "${sandboxing_method%%,}" +} + +function show_service_status_details() +{ + local user_name="$1" + + # query systemd for service state and determine sandboxing method + if [ "$user_name" == "root" ]; then + local svc_state=$(systemctl show -p SubState --value "$svc_name" 2>&1) + else + local svc_state=$(su - "$user" -c "systemctl --user show -p SubState --value \"$svc_name\"" 2>&1) + fi + + local is_generated=1 + local is_isu_sandboxed=1 + local is_systemd_mount_file_sandboxing=1 + local is_systemd_bind_paths=1 + local all_mounts_successful=1 + local is_svc_installed=1 + + local detailed_svc_state + if [ "$user_name" == "root" ]; then + local detailed_svc_state=$(systemctl status "$svc_name" 2>&1) + else + local detailed_svc_state=$(su - "$user" -c "systemctl --user status \"$svc_name\"" 2>&1) + fi + grep -qv 'Unit .*\.service could not be found' <<< "$detailed_svc_state" || { + echo "Service file: $svc_name.service not found" + return + } + + if [ "$user_name" == "root" ]; then + grep -q 'loaded (/run/systemd/generator' <<< "$detailed_svc_state" || is_generated=0 + else + grep -q 'loaded (/run/user/.*; generated)' <<< "$detailed_svc_state" || is_generated=0 + fi + + # determine sandboxing method + grep -q '/bin/isu-sandbox' <<< "$detailed_svc_state" || is_isu_sandboxed=0 + + if [ "$user_name" == "root" ]; then + local svc_file=$(systemctl cat "$svc_name" 2>&1) + else + local svc_file=$(su - "$user" -c "systemctl --user cat \"$svc_name\"" 2>&1) + fi + + if [ "$is_isu_sandboxed" == 0 ]; then + grep -q '/bin/isu-sandbox' <<< "$svc_file" && is_isu_sandboxed=1 + fi + + query_systemd_mount_files + + grep -q 'BindPaths\|BindReadOnlyPaths\|TemporaryFileSystem' <<< "$svc_file" || is_systemd_bind_paths=0 + + # do not show status for `*.mount.service` file + if [ -z "${svc_name##*.mount}" ]; then + return + fi + + # show isu package info, status and sandboxing method (optional) + echo -n "$pkg_name " + if [ -n "$version" ]; then + echo -n "($version) " + fi + + if [ -n "$sys_version" ] && [ "$verbose" == "1" ]; then + echo -n "(system package version: $sys_version) " + fi + + echo -n "[$svc_name.service] " + if [ "$user_name" != "root" ]; then + echo -n "[user: $user]: " + fi + + echo -n "$svc_state" + + if [ "$verbose" != 1 ]; then + echo "" + return + fi + + if [ "$is_generated" == "1" ]; then + echo -n ", " + show_sandboxing_method + fi +} + +function show_service_status_single() +{ + IFS=' ' read -r -a svc_names_arr <<< "$2" + + for i in "${svc_names_arr[@]}"; do + if [ -z "$i" ] || [ -z "${i%%service}" ]; then + continue + fi + svc_name=${i%%.service} + show_service_status_details "$1" + done +} + +function show_system_service_status_single() +{ + show_service_status_single "root" "$@" +} + +function show_user_service_status_single() +{ + for user in $systemd_users; do + show_service_status_single "$user" "$@" + done +} + +function isu_status_single() +{ + local pkg_name="${1%.service}" + local verbose="${2:-0}" + local isu_cfg_file=$(cat "$ISU_CFGS_PATH/$pkg_name/isu.cfg" 2>/dev/null) + local sys_version=$(grep -e '^version' <<< "$isu_cfg_file" 2>/dev/null | awk -F '=' '{gsub(/[ ]+/,""); print $2}') + local isu_run_cfg_file=$(cat "$ISU_RUN_PATH/$pkg_name/isu.cfg" 2>/dev/null) + local version=$(grep -e '^version' <<< "$isu_run_cfg_file" 2>/dev/null | awk -F '=' '{gsub(/[ ]+/,""); print $2}') + local svc_names=$(grep -e 'system_service\|user_service' <<< "$isu_run_cfg_file" 2>/dev/null | awk -F '=' '{print $2}') + local svc_name + local is_user_service=1 + + svc_names=${svc_names:=${1%.service}} + if [ -z "$svc_names" ] || [ -z "$version" ]; then + echo "Cannot find the correct isu config file for package: $pkg_name" + return + fi + + grep -q 'user_service' <<< "$isu_run_cfg_file" || is_user_service=0 + + if [ "$is_user_service" == 0 ]; then + show_system_service_status_single "$svc_names" + else + show_user_service_status_single "$svc_names" + fi +} + +function query_all_service_statuses() +{ + local isu_dirs=$(compgen -G "$ISU_RUN_PATH/*" 2>/dev/null) + if [ -z "$isu_dirs" ]; then + echo "No isu packages." + return + fi + for pkg_path in $isu_dirs; do + local pkg_name=$(basename "$pkg_path") + isu_status_single "$pkg_name" "$2" + done +} + +function isu_status() +{ + local pkg_name="$1" + local verbose_flag="$2" + local systemd_users=$(ps axo user:100,args | awk '$2 == "/usr/lib/systemd/systemd" && $3 == "--user" { print $1 }') + + case "$1" in + all) + query_all_service_statuses "$@" + ;; + *) + isu_status_single "$pkg_name" "$verbose_flag" + esac +} + function verify_checksum() { local pkg_path="$1" @@ -159,6 +390,32 @@ case $1 in list) list_pkgs ;; + status) + verbose=0 + shift 1 + + while getopts "v" arg; do + case $arg in + v) + verbose=1 + ;; + *) + print_status_help + exit + ;; + esac + done + + shift $((OPTIND-1)) + + if [ $# -eq 1 ]; then + isu_status "$1" "$verbose" + elif [ $# -eq 0 ]; then + isu_status "all" "$verbose" + else + print_status_help + fi + ;; install) force=0 restart_after_install=0