Ubuntu 24 Support for Sashimono (#416)

This commit is contained in:
Kithmini Gunawardhana
2024-10-14 09:16:09 +05:30
committed by GitHub
parent d607729587
commit 3df2fe4586
12 changed files with 211 additions and 301 deletions

View File

@@ -15,62 +15,67 @@ if [ ! -f "$saconfig" ]; then
exit 1
fi
# Calculate resources
# Function to create or update cgroup limits based on user and process
apply_limits() {
# Read config values
max_mem_kbytes=$(jq '.system.max_mem_kbytes' $saconfig)
max_swap_kbytes=$(jq '.system.max_swap_kbytes' $saconfig)
max_cpu_us=$(jq '.system.max_cpu_us' $saconfig)
max_instance_count=$(jq '.system.max_instance_count' $saconfig)
echo "Apply limits $1"
([ "$max_instance_count" == "" ] || [ ${#max_instance_count} -eq 0 ] || [ "$max_instance_count" -le 0 ]) && echo "max_instance_count cannot be empty." && exit 1
local user=$1
local user_id=$(id -u $user)
local max_mem_kbytes=$(jq '.system.max_mem_kbytes' $saconfig)
local max_swap_kbytes=$(jq '.system.max_swap_kbytes' $saconfig)
local max_cpu_us=$(jq '.system.max_cpu_us' $saconfig)
local max_instance_count=$(jq '.system.max_instance_count' $saconfig)
local cores=$(grep -c ^processor /proc/cpuinfo)
instance_mem_kbytes=0
if [ "$max_mem_kbytes" != "" ] && [ ! ${#max_mem_kbytes} -eq 0 ] && [ "$max_mem_kbytes" -gt 0 ]; then
! instance_mem_kbytes=$(expr $max_mem_kbytes / $max_instance_count) && echo "Max memory limit calculation error." && exit 1
([ "$max_instance_count" == "" ] || [ ${#max_instance_count} -eq 0 ] || [ "$max_instance_count" -le 0 ]) && echo "max_instance_count cannot be empty." && exit 1
local instance_mem_kbytes=0
if [ "$max_mem_kbytes" != "" ] && [ ! ${#max_mem_kbytes} -eq 0 ] && [ "$max_mem_kbytes" -gt 0 ]; then
! instance_mem_kbytes=$(expr $max_mem_kbytes / $max_instance_count) && echo "Max memory limit calculation error." && exit 1
fi
local instance_swap_kbytes=0
if [ "$max_swap_kbytes" != "" ] && [ ! ${#max_swap_kbytes} -eq 0 ] && [ "$max_swap_kbytes" -gt 0 ]; then
! instance_swap_kbytes=$(expr $instance_mem_kbytes + $max_swap_kbytes / $max_instance_count) && echo "Max swap memory limit calculation error." && exit 1
fi
local instance_cpu_quota=0
# In the Sashimono configuration, CPU time is 1000000us Sashimono is given max_cpu_us out of it.
# Instance allocation is multiplied by number of cores to determined the number of cores per instance and devided by 10 since cfs_period_us is set to 100000us
local CPU_PERIOD="1000000" # in microseconds
if [ "$max_cpu_us" != "" ] && [ ! ${#max_cpu_us} -eq 0 ] && [ "$max_cpu_us" -gt 0 ]; then
cores=$(grep -c ^processor /proc/cpuinfo)
! instance_cpu_quota=$(expr $(expr $cores \* $max_cpu_us \* 100) / $(expr $max_instance_count \* $CPU_PERIOD)) && echo "Max cpu limit calculation error." && exit 1
fi
echo "[Slice]
CPUQuota=${instance_cpu_quota}%
MemoryMax=${instance_mem_kbytes}K
MemorySwapMax=${instance_swap_kbytes}K" | sudo tee /etc/systemd/system/user-$user_id.slice.d/override.conf
sudo systemctl daemon-reload
sudo systemctl restart user-$user_id.slice
}
osversion=$(grep -ioP '^VERSION_ID="\K[^"]+' /etc/os-release)
if [ "$osversion" == "24.04" ]; then
# Allow unpriviledged user namespaces (By Default restricted in Ubuntu 24.04)
sudo sysctl -w kernel.apparmor_restrict_unprivileged_unconfined=0
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
fi
instance_swap_kbytes=0
if [ "$max_swap_kbytes" != "" ] && [ ! ${#max_swap_kbytes} -eq 0 ] && [ "$max_swap_kbytes" -gt 0 ]; then
! instance_swap_kbytes=$(expr $instance_mem_kbytes + $max_swap_kbytes / $max_instance_count) && echo "Max swap memory limit calculation error." && exit 1
fi
instance_cpu_quota=0
# In the Sashimono configuration, CPU time is 1000000us Sashimono is given max_cpu_us out of it.
# Instance allocation is multiplied by number of cores to determined the number of cores per instance and devided by 10 since cfs_period_us is set to 100000us
if [ "$max_cpu_us" != "" ] && [ ! ${#max_cpu_us} -eq 0 ] && [ "$max_cpu_us" -gt 0 ]; then
cores=$(grep -c ^processor /proc/cpuinfo)
! instance_cpu_quota=$(expr $(expr $cores \* $max_cpu_us) / $(expr $max_instance_count \* 10)) && echo "Max cpu limit calculation error." && exit 1
fi
prefix="sashi"
cgroupsuffix="-cg"
users=$(cut -d: -f1 /etc/passwd | grep "^$prefix" | sort)
# Monitor processes and assign them to appropriate cgroups
# Get usernames matching the pattern
users=$(cut -d: -f1 /etc/passwd | grep "^sashi" | sort)
readarray -t userarr <<<"$users"
validusers=()
for user in "${userarr[@]}"; do
[ ${#user} -lt 24 ] || [ ${#user} -gt 32 ] || [[ ! "$user" =~ ^$prefix[0-9]+$ ]] && continue
validusers+=("$user")
done
has_err=0
for user in "${validusers[@]}"; do
# Setup user cgroup.
if [ $instance_cpu_quota -gt 0 ] &&
! (cgcreate -g cpu:$user$cgroupsuffix &&
echo "100000" >/sys/fs/cgroup/cpu/$user$cgroupsuffix/cpu.cfs_period_us &&
echo "$instance_cpu_quota" >/sys/fs/cgroup/cpu/$user$cgroupsuffix/cpu.cfs_quota_us); then
echo "CPU cgroup creation for $user failed."
has_err=1
fi
if [ $instance_mem_kbytes -gt 0 ] &&
! (cgcreate -g memory:$user$cgroupsuffix &&
echo "${instance_mem_kbytes}K" >/sys/fs/cgroup/memory/$user$cgroupsuffix/memory.limit_in_bytes &&
echo "${instance_swap_kbytes}K" >/sys/fs/cgroup/memory/$user$cgroupsuffix/memory.memsw.limit_in_bytes); then
echo "Memory cgroup creation for $user failed."
has_err=1
fi
for user in "${userarr[@]}"; do
[ ${#user} -lt 24 ] || [ ${#user} -gt 32 ] || [[ ! "$user" =~ ^sashi[0-9]+$ ]] && continue
! apply_limits "$user" && has_err=1
done
[ $has_err -eq 1 ] && exit 1

View File

@@ -41,13 +41,11 @@ docker_pull_timeout_secs=120
cleanup_script=$user_dir/uninstall_cleanup.sh
gp_udp_port_count=2
gp_tcp_port_count=2
osversion=$(grep -ioP '^VERSION_ID=\K.+' /etc/os-release | tr -d '"')
# Check if users already exists.
[ "$(id -u "$user" 2>/dev/null || echo -1)" -ge 0 ] && echo "HAS_USER,INST_ERR" && exit 1
# Check cgroup mounts exists.
{ [ ! -d /sys/fs/cgroup/cpu ] || [ ! -d /sys/fs/cgroup/memory ]; } && echo "CGROUP_ERR,INST_ERR" && exit 1
function rollback() {
echo "Rolling back user installation. $1"
"$script_dir"/user-uninstall.sh "$user"
@@ -199,6 +197,23 @@ for ((i = 0; i < $gp_tcp_port_count; i++)); do
fi
done
# Creating AppArmor Profile for unpriviledged user on Ubuntu 24.04
if [ "$osversion" == "24.04" ]; then
filename=$(echo /home/$user/bin/rootlesskit | sed -e s@^/@@ -e s@/@.@g)
cat <<EOF > /etc/apparmor.d/$filename
abi <abi/4.0>,
include <tunables/global>
"/home/$user/bin/rootlesskit" flags=(unconfined) {
userns,
include if exists <local/$filename>
}
EOF
chown $user:$user /etc/apparmor.d/$filename
systemctl restart apparmor.service
fi
echo "Installing rootless dockerd for user."
sudo -H -u "$user" PATH="$docker_bin":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$docker_bin"/dockerd-rootless-setuptool.sh install
@@ -303,15 +318,25 @@ sudo -u "$user" XDG_RUNTIME_DIR="$user_runtime_dir" systemctl --user daemon-relo
# In the Sashimono configuration, CPU time is 1000000us Sashimono is given max_cpu_us out of it.
# Instance allocation is multiplied by number of cores to determined the number of cores per instance and devided by 10 since cfs_period_us is set to 100000us
cores=$(grep -c ^processor /proc/cpuinfo)
cpu_quota=$(expr $(expr $cores \* $cpu) / 10)
cpu_period=1000000
cpu_quota=$(expr $(expr $cores \* $cpu \* 100 \/ $cpu_period))
echo "Setting up user cgroup resources."
! (cgcreate -g cpu:$user$cgroupsuffix &&
echo "100000" >/sys/fs/cgroup/cpu/$user$cgroupsuffix/cpu.cfs_period_us &&
echo "$cpu_quota" >/sys/fs/cgroup/cpu/$user$cgroupsuffix/cpu.cfs_quota_us) && rollback "CGROUP_CPU_CREAT"
! (cgcreate -g memory:$user$cgroupsuffix &&
echo "${memory}K" >/sys/fs/cgroup/memory/$user$cgroupsuffix/memory.limit_in_bytes &&
echo "${swapmem}K" >/sys/fs/cgroup/memory/$user$cgroupsuffix/memory.memsw.limit_in_bytes) && rollback "CGROUP_MEM_CREAT"
echo "Configured user cgroup resources."
# Resource limiting for the unpriviledged user
mkdir /etc/systemd/system/user-$user_id.slice.d
touch /etc/systemd/system/user-$user_id.slice.d/override.conf
echo "[Slice]
Slice=user.slice
MemoryMax=${memory}K
CPUQuota=${cpu_quota}%
MemorySwapMax=${swapmem}K" | sudo tee /etc/systemd/system/user-$user_id.slice.d/override.conf
# Add all current members of the group to the cgroup
# apply_cgroups $user
systemctl daemon-reload
echo "$user_id,$user,$dockerd_socket,INST_SUC"
exit 0

View File

@@ -32,15 +32,7 @@ docker_bin=$script_dir/dockerbin
cleanup_script=$user_dir/uninstall_cleanup.sh
gp_udp_port_count=2
gp_tcp_port_count=2
function cgrulesengd_servicename() {
# Find the cgroups rules engine service.
local cgrulesengd_filepath=$(grep "ExecStart.*=.*/cgrulesengd$" /etc/systemd/system/*.service | head -1 | awk -F : ' { print $1 } ')
if [ -n "$cgrulesengd_filepath" ]; then
local cgrulesengd_filename=$(basename $cgrulesengd_filepath)
echo "${cgrulesengd_filename%.*}"
fi
}
osversion=$(grep -ioP '^VERSION_ID=\K.+' /etc/os-release | tr -d '"')
echo "Uninstalling user '$user'."
@@ -80,10 +72,8 @@ while true; do
pkill -SIGKILL -u "$user"
done
echo "Removing cgroups"
# Delete config values.
cgdelete -g cpu:$user$cgroupsuffix
cgdelete -g memory:$user$cgroupsuffix
echo "Removing cgroups user slice override configuration"
sudo rmdir /etc/systemd/system/user-$user_id.slice.d
# Removing applied disk quota of the user before deleting.
setquota -g -F vfsv0 "$user" 0 0 0 0 /
@@ -151,17 +141,20 @@ if [ -f $cleanup_script ]; then
/bin/bash -c $cleanup_script
fi
# Removing AppArmor Profile
if [ "$osversion" == "24.04" ]; then
echo "Removing AppArmor Profile '$user'"
[ -f "/etc/apparmor.d/home.${user}.bin.rootlesskit" ] && sudo rm -r "/etc/apparmor.d/home.${user}.bin.rootlesskit"
fi
echo "Deleting user '$user'"
userdel "$user"
rm -r /home/"${user:?}"
# Even though we are creating a group specifically,
# It'll be automatically deleted when we delete the user.
cgrulesengd_service=$(cgrulesengd_servicename)
if [ ! -z "$cgrulesengd_service" ]; then
echo "Restarting the '$cgrulesengd_service' service..."
systemctl restart $cgrulesengd_service
fi
# Removing process and file desctiptor limitations for the user after user deletion.
sudo sed -i "/^$user/d" /etc/security/limits.conf
# Removing process and file desctiptor limitations for the user after user deletion.
sudo sed -i "/^$user/d" /etc/security/limits.conf

View File

@@ -13,8 +13,8 @@ if [ -z "$(ls -A $docker_bin 2>/dev/null)" ]; then
tmp=$(mktemp -d)
cd $tmp
curl -s https://download.docker.com/linux/static/stable/x86_64/docker-24.0.5.tgz --output docker.tgz
curl -s https://download.docker.com/linux/static/stable/x86_64/docker-rootless-extras-24.0.5.tgz --output rootless.tgz
curl -s https://download.docker.com/linux/static/stable/x86_64/docker-27.0.1.tgz --output docker.tgz
curl -s https://download.docker.com/linux/static/stable/x86_64/docker-rootless-extras-27.0.1.tgz --output rootless.tgz
cd $docker_bin
tar zxf $tmp/docker.tgz --strip-components=1

View File

@@ -5,7 +5,6 @@
# Adding user disk quota limitation capability
# Enable user quota in fstab for root mount.
# Enable cgroup memory and swapaccount capability.
# Setup cgroups rules engine service.
echo "---Sashimono prerequisites installer---"
@@ -14,9 +13,6 @@ tmpfstab=$tmp.tmp
originalfstab=/etc/fstab
cp $originalfstab "$tmpfstab"
backup=$originalfstab.sashi.bk
cgrulesengd_service=$1 # cgroups rules engine service name
[ -z "$cgrulesengd_service" ] && cgrulesengd_service="cgrulesengd"
function stage() {
echo "STAGE $1" # This is picked up by the setup console output filter.
@@ -82,6 +78,18 @@ if ! command -v snap &>/dev/null; then
apt-get install -y snapd
fi
# Install snap (required for letsencrypt certbot install)
if ! command -v dbus-user-session &>/dev/null; then
stage "Installing dbus-ser-session"
apt-get install -y dbus-user-session
fi
if ! command -v systemd-container &>/dev/null; then
stage "Installing systemd-container"
apt-get install -y systemd-container
fi
# -------------------------------
# fstab changes
# We do not edit original file, instead we create a temp file with original and edit it.
@@ -183,43 +191,6 @@ else
echo "Fuse config already updated."
fi
# -------------------------------
stage "Configuring cgroup rules engine"
# Copy cgred.conf from examples if not exists to setup control groups.
[ ! -f /etc/cgred.conf ] && cp /usr/share/doc/cgroup-tools/examples/cgred.conf /etc/
# Create new cgconfig.conf if not exists to setup control groups.
[ ! -f /etc/cgconfig.conf ] && : >/etc/cgconfig.conf
# Create new cgrules.conf if not exists to setup control groups.
[ ! -f /etc/cgrules.conf ] && : >/etc/cgrules.conf
# Setup a service if not exists to run cgroup rules generator.
cgrulesengd_file="/etc/systemd/system/$cgrulesengd_service.service"
if ! [ -f "$cgrulesengd_file" ]; then
echo "[Unit]
Description=cgroups rules generator
After=network.target
[Service]
User=root
Group=root
Type=forking
EnvironmentFile=-/etc/cgred.conf
ExecStart=/usr/sbin/cgrulesengd
Restart=on-failure
[Install]
WantedBy=multi-user.target" >$cgrulesengd_file
systemctl daemon-reload
fi
systemctl enable $cgrulesengd_service
systemctl start $cgrulesengd_service
# -------------------------------
stage "Configuring grub"
# Enable cgroup memory and swapaccount if not already configured
# We create a temp of the grub file and replace with original file only if success.
tmp=$(mktemp -d)
@@ -227,72 +198,89 @@ tmpgrub=$tmp.tmp
cp /etc/default/grub "$tmpgrub"
updated=0
# Check GRUB_CMDLINE_LINUX exists, create new if not exists.
# If exists check for cgroup_enable=memory and swapaccount=1 and configure them if not already configured.
sed -n -r -e "/^GRUB_CMDLINE_LINUX=/{q100}" "$tmpgrub"
res=$?
if [ $res -eq 100 ]; then
# Check cgroup_enable=memory exists, create new if not exists otherwise skip.
sed -n -r -e "/^GRUB_CMDLINE_LINUX=/{ /cgroup_enable=memory/{q100}; }" "$tmpgrub"
res=$?
if [ $res -eq 0 ]; then
sed -i -r -e "/^GRUB_CMDLINE_LINUX=/{ s/\"\s*\$/ cgroup_enable=memory\"/ }" "$tmpgrub"
res=$?
updated=1
fi
# If there's no error.
if [ $res -eq 0 ] || [ $res -eq 100 ]; then
# Check swapaccount=1 exists, create new if not exists otherwise skip.
sed -n -r -e "/^GRUB_CMDLINE_LINUX=/{ /swapaccount=1/{q100}; }" "$tmpgrub"
if mount | grep "type cgroup2" | grep -q "/sys/fs/cgroup/unified"; then
stage "Configuring grub"
stage "Enabling Cgroups unified hierarchy"
sed -n -r -e "/^GRUB_CMDLINE_LINUX=/{q100}" "$tmpgrub"
res=$?
if [ $res -eq 100 ]; then
# Check systemd.unified_cgroup_hierarchy=1exists, create new if not exists otherwise skip.
sed -n -r -e "/^GRUB_CMDLINE_LINUX=/{ /systemd.unified_cgroup_hierarchy=1/{q100}; }" "$tmpgrub"
res=$?
if [ $res -eq 0 ]; then
# Check whether there's swapaccount value other than 1, If so replace value with 1.
# Otherwise add swapaccount=1 after cgroup_enable=memory.
sed -n -r -e "/^GRUB_CMDLINE_LINUX=/{ /swapaccount=/{q100}; }" "$tmpgrub"
sed -i -r -e "/^GRUB_CMDLINE_LINUX=/{ s/\"\s*\$/ systemd.unified_cgroup_hierarchy=1\"/ }" "$tmpgrub"
res=$?
if [ $res -eq 100 ]; then
sed -i -r -e "/^GRUB_CMDLINE_LINUX=/{ s/swapaccount=[0-9]*/swapaccount=1/ }" "$tmpgrub"
res=$?
updated=1
elif [ $res -eq 0 ]; then
sed -i -r -e "/^GRUB_CMDLINE_LINUX=/{ s/cgroup_enable=memory/cgroup_enable=memory swapaccount=1/ }" "$tmpgrub"
updated=1
fi
# If there's no error.
if [ $res -eq 0 ] || [ $res -eq 100 ]; then
# Check cgroup_enable=memory exists, create new if not exists otherwise skip.
sed -n -r -e "/^GRUB_CMDLINE_LINUX=/{ /cgroup_enable=memory/{q100}; }" "$tmpgrub"
res=$?
if [ $res -eq 0 ]; then
sed -i -r -e "/^GRUB_CMDLINE_LINUX=/{ s/\"\s*\$/ cgroup_enable=memory\"/ }" "$tmpgrub"
res=$?
updated=1
fi
fi
fi
elif [ $res -eq 0 ]; then
echo "GRUB_CMDLINE_LINUX=\"cgroup_enable=memory swapaccount=1\"" >>"$tmpgrub"
res=$?
updated=1
fi
# If the res is not success(0) or alredy exist(100).
[ ! $res -eq 0 ] && [ ! $res -eq 100 ] && echo "Grub GRUB_CMDLINE_LINUX update failed." && exit 1
# If updated we do update-grub and reboot.
if [ $updated -eq 1 ]; then
# Create a backup of original grub, So we can replace the backup with original if update-grub failed.
grub_backup=/etc/default/grub.sashi.bk
cp /etc/default/grub $grub_backup
mv "$tmpgrub" /etc/default/grub
rm -r "$tmp"
if ! update-grub >/dev/null 2>&1; then
mv $grub_backup /etc/default/grub
echo "Grub update failed."
exit 1
# If there's no error.
if [ $res -eq 0 ] || [ $res -eq 100 ]; then
# Check swapaccount=1 exists, create new if not exists otherwise skip.
sed -n -r -e "/^GRUB_CMDLINE_LINUX=/{ /swapaccount=1/{q100}; }" "$tmpgrub"
res=$?
if [ $res -eq 0 ]; then
# Check whether there's swapaccount value other than 1, If so replace value with 1.
# Otherwise add swapaccount=1 after cgroup_enable=memory.
sed -n -r -e "/^GRUB_CMDLINE_LINUX=/{ /swapaccount=/{q100}; }" "$tmpgrub"
res=$?
if [ $res -eq 100 ]; then
sed -i -r -e "/^GRUB_CMDLINE_LINUX=/{ s/swapaccount=[0-9]*/swapaccount=1/ }" "$tmpgrub"
res=$?
updated=1
elif [ $res -eq 0 ]; then
sed -i -r -e "/^GRUB_CMDLINE_LINUX=/{ s/cgroup_enable=memory/cgroup_enable=memory swapaccount=1/ }" "$tmpgrub"
res=$?
updated=1
fi
fi
fi
elif [ $res -eq 0 ]; then
echo "GRUB_CMDLINE_LINUX=\"systemd.unified_cgroup_hierarchy=1 cgroup_enable=memory swapaccount=1\"" >>"$tmpgrub"
res=$?
updated=1
fi
# Indicate pending reboot in the standard reboot required file.
touch /run/reboot-required
rebootpkgs=/run/reboot-required.pkgs
(! [ -f $rebootpkgs ] || [ -z "$(grep sashimono $rebootpkgs)" ]) && echo "sashimono" >>$rebootpkgs
# If the res is not success(0) or alredy exist(100).
[ ! $res -eq 0 ] && [ ! $res -eq 100 ] && echo "Grub GRUB_CMDLINE_LINUX update failed." && exit 1
echo "Updated grub. System needs to be rebooted to apply grub changes."
else
rm -r "$tmp"
echo "Grub already configured."
# If updated we do update-grub and reboot.
if [ $updated -eq 1 ]; then
# Create a backup of original grub, So we can replace the backup with original if update-grub failed.
grub_backup=/etc/default/grub.sashi.bk
cp /etc/default/grub $grub_backup
mv "$tmpgrub" /etc/default/grub
rm -r "$tmp"
if ! update-grub >/dev/null 2>&1; then
mv $grub_backup /etc/default/grub
echo "Grub update failed."
exit 1
fi
# Indicate pending reboot in the standard reboot required file.
touch /run/reboot-required
rebootpkgs=/run/reboot-required.pkgs
(! [ -f $rebootpkgs ] || [ -z "$(grep sashimono $rebootpkgs)" ]) && echo "sashimono" >>$rebootpkgs
echo "Updated grub. System needs to be rebooted to apply grub changes."
else
rm -r "$tmp"
echo "Grub already configured."
fi
fi
exit 0

View File

@@ -175,19 +175,10 @@ function call_third_party() {
return 1
}
function cgrulesengd_servicename() {
# Find the cgroups rules engine service.
local cgrulesengd_filepath=$(grep "ExecStart.*=.*/cgrulesengd$" /etc/systemd/system/*.service | head -1 | awk -F : ' { print $1 } ')
if [ -n "$cgrulesengd_filepath" ]; then
local cgrulesengd_filename=$(basename $cgrulesengd_filepath)
echo "${cgrulesengd_filename%.*}"
fi
}
function set_cpu_info() {
[ -z $cpu_model_name ] && cpu_model_name=$(lscpu | grep -i "^Model name:" | sed 's/Model name://g; s/[#$%*@;]//g' | xargs | tr ' ' '_')
[ -z $cpu_count ] && cpu_count=$(lscpu | grep -i "^CPU(s):" | sed 's/CPU(s)://g' | xargs)
[ -z $cpu_mhz ] && cpu_mhz=$(lscpu | grep -i "^CPU MHz:" | sed 's/CPU MHz://g' | sed 's/\.[0-9]*//g' | xargs)
[ -z $cpu_model_name ] && cpu_model_name=$(cat /proc/cpuinfo | grep -m 1 "model name" | sed -n 's/model name\s*: //p' | sed 's/ /_/g')
[ -z $cpu_count ] && cpu_count=$(grep -c ^processor /proc/cpuinfo)
[ -z $cpu_mhz ] && cpu_mhz=$(cat /proc/cpuinfo | grep -m 1 "cpu MHz" | sed -n 's/cpu MHz\s*: //p')
}
function setup_certbot_renewal() {
@@ -453,13 +444,10 @@ function upgrade() {
return 0
}
# Check cgroup rule config exists.
[ ! -f /etc/cgred.conf ] && echo "cgroups is not configured. Make sure you've installed and configured cgroup-tools." && exit 1
# Stop services before start upgrade.
if [[ "$UPGRADE" == "1" ]]; then
systemctl stop $SASHIMONO_SERVICE
systemctl stop $CGCREATE_SERVICE
sudo -u "$MB_XRPL_USER" XDG_RUNTIME_DIR="$mb_user_runtime_dir" systemctl --user stop $MB_XRPL_SERVICE
fi
@@ -492,7 +480,6 @@ rm -r "$tmp"
# Install Sashimono agent binaries into sashimono bin dir.
cp "$script_dir"/{sagent,hpfs,user-cgcreate.sh,user-install.sh,user-uninstall.sh,docker-registry-uninstall.sh} $SASHIMONO_BIN
chmod -R +x $SASHIMONO_BIN
# Setup tls certs used for contract instance websockets.
[ "$UPGRADE" == "0" ] && setup_tls_certs
@@ -578,21 +565,10 @@ fi
stage "Configuring Sashimono services"
cgrulesengd_service=$(cgrulesengd_servicename)
[ -z "$cgrulesengd_service" ] && echo "cgroups rules engine service does not exist." && abort
# Setting up cgroup rules with sashiusers group (if not already setup).
echo "Creating cgroup rules..."
! grep -q $SASHIUSER_GROUP /etc/group && ! groupadd $SASHIUSER_GROUP && echo "$SASHIUSER_GROUP group creation failed." && abort
if ! grep -q $SASHIUSER_GROUP /etc/cgrules.conf; then
! echo "@$SASHIUSER_GROUP cpu,memory %u$CG_SUFFIX" >>/etc/cgrules.conf && echo "Cgroup rule creation failed." && abort
# Restart the service to apply the cgrules config.
echo "Restarting the '$cgrulesengd_service' service."
systemctl restart $cgrulesengd_service || abort
fi
# Install Sashimono Agent cgcreate service.
# This is a oneshot service which runs once at system startup. The intention is to run 'cgcreate' for
# This is a oneshot service which runs once at system startup. This update user slices
# all sashimono users every time the system boots up.
echo "[Unit]
Description=Sashimono cgroup creation service.
@@ -604,7 +580,6 @@ Type=oneshot
ExecStart=$SASHIMONO_BIN/user-cgcreate.sh $SASHIMONO_DATA
[Install]
WantedBy=multi-user.target" >/etc/systemd/system/$CGCREATE_SERVICE.service
echo "Configuring sashimono agent service..."
# Since gp ports are added as new feature we manually configure the default on upgrade mode if not exists.

View File

@@ -79,15 +79,6 @@ function exec_mb() {
return $return_code
}
function cgrulesengd_servicename() {
# Find the cgroups rules engine service.
local cgrulesengd_filepath=$(grep "ExecStart.*=.*/cgrulesengd$" /etc/systemd/system/*.service | head -1 | awk -F : ' { print $1 } ')
if [ -n "$cgrulesengd_filepath" ]; then
local cgrulesengd_filename=$(basename $cgrulesengd_filepath)
echo "${cgrulesengd_filename%.*}"
fi
}
function cleanup_certbot_ssl() {
# revoke/delete certs if certbot is used.
if command -v certbot &>/dev/null && [ -f "$SASHIMONO_DATA/sa.cfg" ]; then
@@ -282,16 +273,7 @@ echo "Deleting Sashimono CLI..."
rm $USER_BIN/sashi
if [ "$UPGRADE" == "0" ]; then
# When removing the cgrules service, we first edit the config and restart the service to apply the config.
# Then we remove the attached group.
echo "Deleting cgroup rules..."
sed -i -r "/^@$SASHIUSER_GROUP\s+cpu,memory\s+%u$CG_SUFFIX/d" /etc/cgrules.conf
cgrulesengd_service=$(cgrulesengd_servicename)
[ -z "$cgrulesengd_service" ] && echo "Warning: cgroups rules engine service does not exist."
echo "Restarting the '$cgrulesengd_service' service..."
systemctl restart $cgrulesengd_service
# Remove the attached group.
groupdel $SASHIUSER_GROUP
fi

View File

@@ -11,7 +11,6 @@
evernode="Evernode"
maxmind_creds="687058:FtcQjM0emHFMEfgI"
cgrulesengd_default="cgrulesengd"
alloc_ratio=80
ramKB_per_instance=524288
instances_per_core=3
@@ -28,9 +27,12 @@
root_user="root"
repo_owner="EvernodeXRPL"
repo_name="evernode-resources"
repo_name="evernode-24-resources"
desired_branch="main"
# Regular expression pattern to match "0.*.*"
older_version_pattern="^0\.[0-9]+\.[0-9]+$"
# Reputation modes : 0 - "none", 1 - "OneToOne", 2 - "OneToMany"
is_fresh_reputation_acc=false
reputation_account_mode=0
@@ -201,6 +203,12 @@
echo "$evernode is already installed on your host. You cannot deregister without uninstalling. Use the 'evernode' command to manage your host." &&
exit 1
current_evernode_version=$(jq -r '.version' "$MB_XRPL_CONFIG")
if [[ "$1" == "update" && $current_evernode_version =~ $older_version_pattern ]]; then
echomult "Update not supported on this machine.
\nPlease back up your secrets, transfer your host, and perform a fresh installation instead of proceeding with the upgrade.." && exit 1
fi
[ "$1" != "uninstall" ] && [ "$1" != "status" ] && [ "$1" != "list" ] && [ "$1" != "update" ] && [ "$1" != "log" ] && [ "$1" != "applyssl" ] && [ "$1" != "transfer" ] && [ "$1" != "config" ] && [ "$1" != "delete" ] && [ "$1" != "governance" ] && [ "$1" != "regkey" ] && [ "$1" != "offerlease" ] && [ "$1" != "reputationd" ] &&
echomult "$evernode host management tool
\nYour have $evernode installed on your machine.
@@ -321,7 +329,7 @@
local osversion=$(grep -ioP '^VERSION_ID=\K.+' /etc/os-release)
local errors=""
([ "$os" != "ubuntu" ] || [ "$osversion" != '"20.04"' ]) && errors=" OS: $os $osversion (required: Ubuntu 20.04)\n"
([ "$os" != "ubuntu" ] || [ "$osversion" != '"24.04"' ]) && errors=" OS: $os $osversion (required: Ubuntu 24.04)\n"
[ $ramKB -lt 2000000 ] && errors="$errors RAM: $(GB $ramKB) (required: 2 GB RAM)\n"
[ $swapKB -lt 2000000 ] && errors="$errors Swap: $(GB $swapKB) (required: 2 GB Swap)\n"
[ $diskKB -lt 4000000 ] && errors="$errors Disk space (/home): $(GB $diskKB) (required: 4 GB)\n"
@@ -330,7 +338,7 @@
echo "System check complete. Your system is capable of becoming an $evernode host."
else
echomult "Your system does not meet following $evernode system requirements:\n $errors"
echomult "$evernode host registration requires Ubuntu 20.04 with minimum 2 GB RAM,
echomult "$evernode host registration requires Ubuntu 24.04 with minimum 2 GB RAM,
2 GB Swap and 4 GB free disk space for /home. Aborting setup."
exit 1
fi
@@ -682,16 +690,6 @@
done
}
function check_ipv4_req() {
# Check for IPv4 addresses
local ipv4_addresses=$(ip -4 addr show | grep inet)
if [ -z "$ipv4_addresses" ]; then
echomult "Your system does not support IPv4."
echomult "$evernode host registration requires IPv4 support for dApp deployment."
exit 1
fi
}
function set_ipv6_subnet() {
ipv6_subnet="-"
@@ -750,16 +748,6 @@
done
}
function set_cgrules_svc() {
local filepath=$(grep "ExecStart.*=.*/cgrulesengd$" /etc/systemd/system/*.service | head -1 | awk -F : ' { print $1 } ')
if [ -n "$filepath" ]; then
local filename=$(basename $filepath)
cgrulesengd_service="${filename%.*}"
fi
# If service not detected, use the default name.
[ -z "$cgrulesengd_service" ] && cgrulesengd_service=$cgrulesengd_default || echo "cgroups rules engine service found: '$cgrulesengd_service'"
}
function set_instance_alloc() {
[ -z $alloc_ramKB ] && alloc_ramKB=$(((ramKB / 100) * alloc_ratio))
[ -z $alloc_swapKB ] && alloc_swapKB=$(((swapKB / 100) * alloc_ratio))
@@ -1452,7 +1440,7 @@ WantedBy=timers.target" >/etc/systemd/system/$EVERNODE_AUTO_UPDATE_SERVICE.timer
if [ "$upgrade" == "0" ]; then
echo "Installing other prerequisites..."
! ./prereq.sh $cgrulesengd_service 2>&1 |
! ./prereq.sh 2>&1 |
tee -a >(stdbuf --output=L awk '{ cmd="date -u +\"%Y-%m-%d %H:%M:%S\""; cmd | getline utc_time; close(cmd); print utc_time, $0 }' >>$logfile) | stdbuf --output=L grep -E 'STAGE' |
while read -r line; do
cleaned_line=$(echo "$line" | sed -E 's/STAGE//g' | awk '{sub(/^[ \t]+/, ""); print}')
@@ -2329,7 +2317,6 @@ WantedBy=timers.target" >/etc/systemd/system/$EVERNODE_AUTO_UPDATE_SERVICE.timer
to you since we will be making modifications to your system configuration.
\n\nContinue?" && exit 1
check_ipv4_req
check_sys_req
check_prereq
@@ -2387,9 +2374,6 @@ WantedBy=timers.target" >/etc/systemd/system/$EVERNODE_AUTO_UPDATE_SERVICE.timer
[ ! -f "$MB_XRPL_CONFIG" ] && set_ipv6_subnet
[ "$ipv6_subnet" != "-" ] && [ "$ipv6_net_interface" != "-" ] && echo -e "Using $ipv6_subnet IPv6 subnet on $ipv6_net_interface for contract instances.\n"
set_cgrules_svc
echo -e "Using '$cgrulesengd_service' as cgroups rules engine service.\n"
[ ! -f "$SASHIMONO_CONFIG" ] && set_instance_alloc
echo -e "Using allocation $(GB $alloc_ramKB) memory, $(GB $alloc_swapKB) Swap, $(GB $alloc_diskKB) disk space, distributed among $alloc_instcount contract instances.\n"

View File

@@ -45,7 +45,7 @@ appenv = {
ORPHAN_PRUNE_SCHEDULER_INTERVAL_HOURS: 2,
SASHIMONO_SCHEDULER_INTERVAL_SECONDS: 2,
SASHI_CLI_PATH: appenv.IS_DEV_MODE ? "../build/sashi" : "/usr/bin/sashi",
MB_VERSION: '0.12.1',
MB_VERSION: '1.0.0',
TOS_HASH: '0801677EBCB2F76EF97D531549D8B27DB2C7A4A8EE7F60032AE40184247F0810', // This is the sha256 hash of EVERNODE-HOSTING-PRINCIPLES.pdf.
NETWORK: 'mainnet',
REPUTATIOND_CONFIG_PATH: path.join(appenv.DATA_DIR, '../') + "reputationd/reputationd.cfg",

View File

@@ -32,7 +32,7 @@ namespace hp
// We keep docker logs at size limit of 10mb, We only need these logs for docker instance failure debugging since all other logs are kept in files.
// For the local log driver compression, minimum max-file should be 2. So we keep two logs each max-size is 5mb
constexpr const char *DOCKER_CREATE = "DOCKER_HOST=unix:///run/user/$(id -u %s)/docker.sock timeout --foreground -v -s SIGINT %ss %s/dockerbin/docker create -t -i --stop-signal=SIGINT --log-driver local \
--log-opt max-size=5m --log-opt max-file=2 --name=%s -p %s:%s -p %s:%s -p %s:%s/udp -p %s:%s -p %s:%s -p %s:%s/udp -p %s:%s/udp --restart unless-stopped --mount type=bind,source=%s,target=/contract %s run /contract";
--log-opt max-size=5m --log-opt max-file=2 --name=%s -p %s:%s -p %s:%s -p %s:%s/udp -p %s:%s -p %s:%s -p %s:%s/udp -p %s:%s/udp --security-opt seccomp=unconfined --security-opt apparmor=unconfined --restart unless-stopped --mount type=bind,source=%s,target=/contract %s run /contract";
constexpr const char *DOCKER_START = "DOCKER_HOST=unix:///run/user/$(id -u %s)/docker.sock %s/dockerbin/docker start %s";
constexpr const char *DOCKER_STOP = "DOCKER_HOST=unix:///run/user/$(id -u %s)/docker.sock %s/dockerbin/docker stop %s";
constexpr const char *DOCKER_REMOVE = "DOCKER_HOST=unix:///run/user/$(id -u %s)/docker.sock %s/dockerbin/docker rm -f %s";
@@ -317,7 +317,7 @@ namespace hp
const std::string gp_udp_port_1 = std::to_string(assigned_ports.gp_udp_port_start);
const std::string gp_udp_port_2 = std::to_string(assigned_ports.gp_udp_port_start + 1);
const std::string timeout = std::to_string(DOCKER_CREATE_TIMEOUT_SECS);
const int len = 376 + username.length() + timeout.length() + conf::ctx.exe_dir.length() + container_name.length() + (user_port.length() * 2) + (peer_port.length() * 4) + (gp_tcp_port_1.length() * 2) + (gp_tcp_port_2.length() * 2) + (gp_udp_port_1.length() * 2) + (gp_udp_port_2.length() * 2) + contract_dir.length() + image_name.length();
const int len = 376 + 69 + username.length() + timeout.length() + conf::ctx.exe_dir.length() + container_name.length() + (user_port.length() * 2) + (peer_port.length() * 4) + (gp_tcp_port_1.length() * 2) + (gp_tcp_port_2.length() * 2) + (gp_udp_port_1.length() * 2) + (gp_udp_port_2.length() * 2) + contract_dir.length() + image_name.length();
char command[len];
sprintf(command, DOCKER_CREATE, username.data(), timeout.data(), conf::ctx.exe_dir.data(), container_name.data(),
user_port.data(), user_port.data(),
@@ -1094,58 +1094,16 @@ namespace hp
}
}
/**
* Check whether there's a pending reboot and cgrules service is running and configured.
* Check whether there's a pending reboot
* @return true if active and configured otherwise false.
*/
bool system_ready()
{
char buffer[20];
if (util::execute_bash_cmd(CGRULE_ACTIVE, buffer, 20) == -1)
return false;
// Check cgrules service status is active.
if (strncmp(buffer, "active", 6) != 0)
{
LOG_ERROR << "Cgrules service is inactive.";
return false;
}
// Check cgrules cpu and memory mounts exist.
if (!util::is_dir_exists(CGRULE_CPU_DIR) || !util::is_dir_exists(CGRULE_MEM_DIR))
{
LOG_ERROR << "Cgrules cpu or memory mounts does not exist.";
return false;
}
// Check cgrules config exist and configured.
int fd = open(CGRULE_CONF, O_RDONLY);
if (fd == -1)
{
LOG_ERROR << errno << ": Error opening the cgrules config file.";
return false;
}
std::string buf;
if (util::read_from_fd(fd, buf, 0) == -1)
{
LOG_ERROR << errno << ": Error reading the cgrules config file.";
close(fd);
return false;
}
close(fd);
if (!std::regex_search(buf, std::regex(CGRULE_REGEXP)))
{
LOG_ERROR << "Cgrules config entry does not exist.";
return false;
}
// Check there's a pending reboot.
if (util::is_file_exists(REBOOT_FILE))
{
fd = open(REBOOT_FILE, O_RDONLY);
std::string buf;
int fd = open(REBOOT_FILE, O_RDONLY);
if (fd == -1)
{
LOG_ERROR << errno << ": Error opening the reboot file.";

View File

@@ -6,7 +6,7 @@
namespace version
{
// Sashimono agent version. Written to new configs.
constexpr const char *AGENT_VERSION = "0.12.1";
constexpr const char *AGENT_VERSION = "1.0.0";
// Minimum compatible config version (this will be used to validate configs).
constexpr const char *MIN_CONFIG_VERSION = "0.5.0";