The branch, master has been updated via 9ae866256d908d941880720e71864430a6d8ee24 (commit) from 05a7500abbff09c469962b0518d29c400aed4756 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 9ae866256d908d941880720e71864430a6d8ee24 Author: Guangzhou Nianguan Electronics Technology Co.Ltd <opensource@gznianguan.com> Date: Tue Nov 5 16:26:10 2013 +0100 Add SupeReNicer support. ----------------------------------------------------------------------- Summary of changes: X2Go/{Utils.pm => Config.pm} | 45 ++++--- X2Go/SupeReNicer.pm | 226 +++++++++++++++++++++++++++++++++ X2Go/Utils.pm | 48 ++++++- debian/changelog | 4 + x2goserver-common/etc/x2goserver.conf | 21 +++ x2goserver/sbin/x2gocleansessions | 42 +++++- 6 files changed, 361 insertions(+), 25 deletions(-) copy X2Go/{Utils.pm => Config.pm} (66%) create mode 100644 X2Go/SupeReNicer.pm The diff of changes is: diff --git a/X2Go/Utils.pm b/X2Go/Config.pm similarity index 66% copy from X2Go/Utils.pm copy to X2Go/Config.pm index f5e4cf6..d058753 100644 --- a/X2Go/Utils.pm +++ b/X2Go/Config.pm @@ -20,42 +20,41 @@ # Copyright (C) 2007-2013 Oleksandr Shneyder <oleksandr.shneyder@obviously-nice.de> # Copyright (C) 2007-2013 Heinz-Markus Graesing <heinz-m.graesing@obviously-nice.de> -package X2Go::Utils; +package X2Go::Config; =head1 NAME -X2Go::Utils - X2Go utilities and helper functions for Perl +X2Go::Config - X2Go Config package for Perl =head1 DESCRIPTION -X2Go::Utils Perl package. +X2Go::Config Perl package for X2Go components. =cut use strict; +use Config::Simple; + use base 'Exporter'; +our @EXPORT = ( 'get_config', 'get_sqlconfig', ); + +my $Config; +my $SqlConfig; + +sub get_config { + if (! defined $Config) { + $Config = new Config::Simple(syntax=>'ini'); + $Config->read('/etc/x2go/x2goserver.conf' ); + } + return $Config; +} -our @EXPORT = ('source_environment'); - -sub source_environment { - my $name = shift; - - open my $fh, "<", $name - or return -1; - - while (<$fh>) { - chomp; - my $line = $_; - if ( $line =~ m/^#.*/ ) - { - next; - } - my ($k, $v) = split /=/, $line, 2; - $v =~ s/^(['"])(.*)\1/$2/; #' fix highlighter - $v =~ s/\$([a-zA-Z]\w*)/$ENV{$1}/g; - $v =~ s/`(.*?)`/`$1`/ge; #dangerous - $ENV{$k} = $v; +sub get_sqlconfig { + if (! defined $SqlConfig) { + $SqlConfig = new Config::Simple(syntax=>'ini'); + $SqlConfig->read('/etc/x2go/x2gosql/sql' ); } + return $SqlConfig; } 1; diff --git a/X2Go/SupeReNicer.pm b/X2Go/SupeReNicer.pm new file mode 100644 index 0000000..e08f3ed --- /dev/null +++ b/X2Go/SupeReNicer.pm @@ -0,0 +1,226 @@ +#!/usr/bin/perl + +# Copyright (C) 2013 X2Go Project - http://wiki.x2go.org +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Copyright (C) 2013 Guangzhou Nianguan Electronics Technology Co.Ltd. <opensource@gznianguan.com> +# Copyright (C) 2013 Mike Gabriel <mike.gabriel@das-netzwerkteam.de> + +package X2Go::SuperRenicer; + +=head1 NAME + +X2Go::SuperRenicer- X2Go SuperRenicer package for Perl + +=head1 DESCRIPTION + +X2Go::SuperRenicer Perl package. + +=cut + +use strict; +use Sys::Syslog qw( :standard :macros ); +use X2Go::Utils qw( sanitizer clups ); + +use base 'Exporter'; + +our @EXPORT=('superenice'); + + +sub checkPID { + my $pid = sanitizer("num",$_[0]); + open(PS,"/bin/ps --no-headers -o %u,%p,%n,%c -p $pid|"); + my ($pidInf,undef) = <PS>; + close(PS); + my ($user,$pid,$nice,$cmd) = split(/\,/,clups($pidInf)); + $pid =~ s/\D//g; + return ($pid,$user,$nice,$cmd) +} + + +sub sanitizeNL { + my $NL = shift; + my $fallbackNL = shift; + if ($NL =~ m/^(-|\+|)\d+$/) { + $NL = int $NL; + if ($NL > 19) { $NL = 19; } + elsif ($NL < -19) { $NL = -19; } + } else { + $NL = $fallbackNL; + } + return $NL; +} + + +sub superrenice { + # Normal: Nice LEVEL? + my $normalNL = shift; $normalNL = 0 unless defined $normalNL; + $normalNL = sanitizeNL($normalNL, 0); + # Idle: Nice LEVEL? + my $idleNL = shift; $idleNL = 19 unless defined $idleNL; + $idleNL = sanitizeNL($idleNL, 19); + # Ignore these users (comma separated list as string) + my $ignore_users = shift; $ignore_users = "" unless defined $ignore_users; + # if set to "1" we will force renicing of entire user, even on systems with "/proc" + my $forceUSERrenice = shift; $forceUSERrenice = 0 unless defined $forceUSERrenice; + #Path to the "x2golistsessions_root" perl script... + + my $x2golsrpath = `x2gopath base` . "/sbin/x2golistsessions_root"; + + ########################################################################################### + # Load list of users to "ignore". These users will never be reniced... + my %ignore; + while (split(",", $ignore_users)) {my $iu = clups($_);if (length($iu) > 0) {$ignore{$iu} = 1;}} + # Load list of users to "ignore". These users will never be reniced... + ########################################################################################### + + if ((-f "/proc/$$/environ") and ($forceUSERrenice ne 1)) { + ########################################################################################### + # Great! We're on a system with "/proc" so we're able to do this on individual sessions! + # Basicaly we're checking the users /proc/<$PID>/environ files for the "X2GO_SESSION" env... + my @x2goSessions; + # Read the current list of X2Go sessions and their running state + open(XGOLS,"$x2golsrpath|"); + while (<XGOLS>) { + my $line = clups($_); + my ($agentPid,$x2gosid,undef,undef,$x2goState,undef,undef,undef,undef,undef,undef,$userID,undef,undef) = split(/\|/,$line); + #syslog('debug', "$agentPid,$x2gosid,$x2goState,$userID"); + unless ($ignore{$userID} eq 1) { + push @x2goSessions, "$x2goState:$agentPid:$x2gosid:$userID"; + } + } + close(XGOLS); + + foreach my $x2goSInf (@x2goSessions) { + my ($x2goState,$agentPid,$x2gosid,$userID,undef) = split(/\:/,$x2goSInf); + $agentPid = sanitizer("num",$agentPid); + + # We're only working with "portable" unix usernames. + $userID = sanitizer("anumazcsdaus",$userID); + + # So if the sanitizer returns something we'll do this.... + if ($userID) { + + # Using the NICE value of the agent to figgure out the current nice state... + my ($psP,$psU,$psN,$psC) = checkPID($agentPid); + + if ($x2goState eq "R") { + + # State is R (Running?)... + if ($psN ne $normalNL) { + # If nice level is not normal, renice to normal... + syslog('notice', "ReNicing \"$userID\" to level $normalNL for session \"$x2gosid\""); + # For the sake of getting a user back to normal ASAP... We'll renice the entire user not just individual sessions... + system("renice -n $normalNL -u $userID 1>/dev/null 2>/dev/null"); + } + + } elsif ($x2goState eq "S") { + + # State is S (suspended) + if ($psN ne $idleNL) { + + # Did we renice this? + open(AUPS,"/bin/ps --no-headers -o %u,%p,%n,%c -u $userID|"); # use PS to fetch a list of the users current processes + while (<AUPS>) { + my ($user,$pid,$nice,$cmd) = split(/\,/,clups($_)); + $pid = sanitizer("num",$pid); + + if (-f "/proc/$pid/environ") { + open(ENVIRON,"/proc/$pid/environ");my ($Environ,undef) = <ENVIRON>;close(ENVIRON); + if ($Environ =~ m/X2GO_SESSION=$x2gosid/) { # If the x2go Session ID is in environ... renice the pid... + #syslog('debug', "$pid: X2GO_SESSION=$x2gosid"); + system("renice -n $idleNL -p $pid 1>/dev/null 2>/dev/null"); + } + } + + } + close(AUPS); + + # Renice the AGENT so that we'll know that this one is already reniced. + system("renice -n $idleNL -p $agentPid 1>/dev/null 2>/dev/null"); + syslog('notice', "ReNicing \"$userID\" to level $idleNL for session \"$x2gosid\""); + + } + } + } + } + + # Great! We're on a system with "/proc" so we're able to do this on individual sessions! + ############################################################################################ + + } else { + + ########################################################################################### + # Oh no.... No "/proc"? Lets do this on a per user basis instead then... + # If a user have more than one session, both need to be suspended before we renice.... + # Resuming any of that users sessions would return them all to normal priority. + + my %niceUsers; + # Read the current list of X2Go sessions and their running state + open(XGOLS,"$x2golsrpath|"); + while (<XGOLS>) { + my $line = clups($_); + my ($agentPid,$x2gosid,undef,undef,$x2goState,undef,undef,undef,undef,undef,undef,$userID,undef,undef) = split(/\|/,$line); + syslog('debug', "$agentPid,$x2gosid,,$x2goState,$userID"); + + # If user is in ignore list... we're not going a damn thing.. + unless ($ignore{$userID} eq 1) { + unless ($niceUsers{$userID} =~ /^R:/) { # Basically if we got an R we're sticking with it... + $niceUsers{$userID} = "$x2goState:$agentPid"; + } + } + } + close(XGOLS); + + foreach my $nUser (keys %niceUsers) { + $nUser = sanitizer("anumazcsdaus",$nUser); + + # We're only working with "portable" unix usernames.. + if ($nUser) { + + # So if the sanitizer return something we'll do this.... + my ($x2goState,$agentPid) = split(/\:/, $niceUsers{$nUser}); + + # Using the NICE value of the agent to figgure out the current nice state... + my ($psP,$psU,$psN,$psC) = checkPID($agentPid); + syslog('debug', "$nUser:$x2goState,$agentPid:$psP,$psU,$psN,$psC"); + # State is R (Running?)... + if ($x2goState eq "R") { + + # If nice level is not normal, renice to normal... + if ($psN ne $normalNL) { + syslog('debug', "ReNicing \"$nUser\" to level $normalNL"); + system("renice -n $normalNL -u $nUser 1>/dev/null 2>/dev/null"); + } + + # State is S (suspended) + } elsif ($x2goState eq "S") { + + # Did we renice this? + if ($psN ne $idleNL) { + syslog('debug', "ReNicing \"$nUser\" to level $idleNL"); + system("renice -n $idleNL -u $nUser 1>/dev/null 2>/dev/null"); + } + } + } + } + # Oh no.... No "/proc"? Lets do this on a per user basis instead then... + ########################################################################################### + } +} + +1; diff --git a/X2Go/Utils.pm b/X2Go/Utils.pm index f5e4cf6..928eb67 100644 --- a/X2Go/Utils.pm +++ b/X2Go/Utils.pm @@ -19,6 +19,8 @@ # # Copyright (C) 2007-2013 Oleksandr Shneyder <oleksandr.shneyder@obviously-nice.de> # Copyright (C) 2007-2013 Heinz-Markus Graesing <heinz-m.graesing@obviously-nice.de> +# Copyright (C) 2013 Guangzhou Nianguan Electronics Technology Co.Ltd. <opensource@gznianguan.com> +# Copyright (C) 2013 Mike Gabriel <mike.gabriel@das-netzwerkteam.de> package X2Go::Utils; @@ -35,7 +37,7 @@ X2Go::Utils Perl package. use strict; use base 'Exporter'; -our @EXPORT = ('source_environment'); +our @EXPORT = ('source_environment', 'clups', 'sanitizer', ); sub source_environment { my $name = shift; @@ -58,4 +60,48 @@ sub source_environment { } } +# Over-zealous string sanitizer that makes perl strict and perl -T happy... +sub sanitizer { + my $type = $_[0]; + my $string = $_[1]; + if ($type eq "anumazcs") { + $string =~ s/[^a-zA-Z0-9]//g; + if ($string =~ /^([a-zA-Z0-9]*)$/) { + $string = $1; + return $string; + } else {return 0;} + } elsif ($type eq "anumazlc") { + $string = lc($string); + $string =~ s/[^a-z0-9]//g; + if ($string =~ /^([a-z0-9]*)$/) { + $string = $1; + return $string; + } else {return 0;} + } elsif ($type eq "num") { + $string =~ s/\D//g; + if ($string =~ /^([0-9]*)$/) { + $string = $1; + return $string; + } else {return 0;} + } elsif ($type eq "anumazcsdaus") { + $string =~ s/[^a-zA-Z0-9\_\-]//g; + if ($string =~ /^([a-zA-Z0-9\_\-]*)$/) { + $string = $1; + return $string; + } else {return 0;} + } elsif ($type eq "SOMETHINGELSE") { + return 0; + } else { + return 0; + } +} + +sub clups { + my $string = "@_"; + $string =~ s/\n//g; + $string =~ s/\ //g; + $string =~ s/\s//g; + return $string; +} + 1; diff --git a/debian/changelog b/debian/changelog index 6401701..0328845 100644 --- a/debian/changelog +++ b/debian/changelog @@ -40,6 +40,10 @@ x2goserver (4.1.0.0-0~x2go1) UNRELEASED; urgency=low not set. (Fixes: #82). * Make x2goruncommand aware of the Cinnamon desktop shell. (Fixes: #117). + [ Guangzhou Nianguan Electronics Technology Co.Ltd. ] + * New upstream version (4.1.0.0): + - Add SupeReNicer support. + [ Otto Kjell ] * New upstream version (4.1.0.0): - Add markdown files for most of the X2Go Server project folders. (Fixes: diff --git a/x2goserver-common/etc/x2goserver.conf b/x2goserver-common/etc/x2goserver.conf index 5fa6baf..fc98c90 100644 --- a/x2goserver-common/etc/x2goserver.conf +++ b/x2goserver-common/etc/x2goserver.conf @@ -4,6 +4,27 @@ [limit groups] #bar-group=1 +[security] +# SSHFS umask for client-side folder sharing. Leave uncommented to keep the server's default umask +#umask="0117" + +[superenicer] +# enable the superrenicer code in x2gocleansessions, this will renice suspended sessions to nice level 19 +# and renice them to level 0 if the session becomes marked as running again... +enable=yes + +# list of users that shall never be reniced +#ignored_users= + +# force renicing of the complete user, don't set it to 'yes' unless you know what you are doing +#force-user-renice=no + +# the normal nice level (for running sessions) +#normal-nice-level=0 + +# the idle nice level (for suspended sessions) +#idle-nice-level=19 + [log] # possible levels are: emerg, alert, crit, err, warning, notice, info, debug loglevel=notice diff --git a/x2goserver/sbin/x2gocleansessions b/x2goserver/sbin/x2gocleansessions index 3c9bbf0..728ead3 100755 --- a/x2goserver/sbin/x2gocleansessions +++ b/x2goserver/sbin/x2gocleansessions @@ -21,11 +21,16 @@ # Copyright (C) 2007-2013 Heinz-Markus Graesing <heinz-m.graesing@obviously-nice.de> use strict; + +$ENV{'PATH'} = "/bin:/sbin:/usr/bin:/usr/sbin"; + use Sys::Hostname; use Sys::Syslog qw( :standard :macros ); my $x2go_lib_path = `x2gopath libexec`; -use X2Go::Log qw(loglevel); +use X2Go::Config qw( get_config ); +use X2Go::Log qw( loglevel ); +use X2Go::SupeReNicer qw( superenice ); openlog($0,'cons,pid','user'); setlogmask( LOG_UPTO(loglevel()) ); @@ -107,6 +112,30 @@ elsif ($pid != 0) } elsif ($pid == 0 ) { + + # check if we are to use the superenicer script for throttling does the nice level + # of suspended sessions... + my $Config = get_config(); + + my $superenice_enable=$Config->param("superenicer.enable"); + my $superenice_forceuser=$Config->param("superenicer.force-user-renice"); + my $superenice_normal=$Config->param("superenicer.normal-nice-level"); + my $superenice_idle=$Config->param("superenicer.idle-nice-level"); + my $superenice_ignoredusers=$Config->param("superenicer.ignored-users"); + + if ($superenice_enable =~ m/(1|yes|Yes|YES|on|On|ON|True|true|TRUE)/ ) + { + $superenice_enable=1; + } else { + $superenice_enable=0; + } + if ($superenice_forceuser =~ m/(1|yes|Yes|YES|on|On|ON|True|true|TRUE)/ ) + { + $superenice_forceuser=1; + } else { + $superenice_forceuser=0; + } + # close any open file descriptor left open by our parent before the fork for (glob "/proc/$$/fd/*") { POSIX::close($1) if m{/(\d+)$}; } @@ -115,6 +144,7 @@ elsif ($pid == 0 ) my %remembered_sessions_status = (); my %remembered_sessions_since = (); + my $last_reniced = 0; while(sleep 2) { @@ -201,5 +231,15 @@ elsif ($pid == 0 ) } } } + + # call superenicer script if requested through x2goserver.conf every six seconds + if ( $superenice_enable ) { + $last_reniced += 2; + if ( $last_reniced ge 4 ) { + superenice($superenice_normal, $superenice_idle, $superenice_ignoredusers, $superenice_forceuser); + $last_reniced = 0; + } + } + } } hooks/post-receive -- x2goserver.git (X2Go Server) This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "x2goserver.git" (X2Go Server).