coren has submitted this change and it was merged. Change subject: Tool Labs: completely rejigger the lighttpd setup ......................................................................
Tool Labs: completely rejigger the lighttpd setup Make the port granting reliable, and allow endusers to start their own httpd. Change-Id: I3d55430f3df83644fa158d1f54654675e4d7ed95 --- A modules/toollabs/files/lighttpd-starter A modules/toollabs/files/portgrabber A modules/toollabs/files/portgranter A modules/toollabs/files/portgranter.conf M modules/toollabs/files/tool-lighttpd M modules/toollabs/manifests/exec_environ.pp M modules/toollabs/manifests/webnode.pp 7 files changed, 325 insertions(+), 135 deletions(-) Approvals: coren: Looks good to me, approved jenkins-bot: Verified diff --git a/modules/toollabs/files/lighttpd-starter b/modules/toollabs/files/lighttpd-starter new file mode 100755 index 0000000..64507db --- /dev/null +++ b/modules/toollabs/files/lighttpd-starter @@ -0,0 +1,105 @@ +#! /bin/bash +# +# Copyright © 2013 Marc-André Pelletier <[email protected]> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +tool="$1" +port="$2" +user="local-$tool" +home=$(getent passwd $user | cut -d : -f 6 | sed -e 's/\/$//') +if [ "$(getent group $user | cut -d : -f 1)" != "$user" ]; then + echo "$0: $1 does not appear to be a tool" >&2 + exit 1 +fi +spool="/var/run/lighttpd" +runbase="$spool/$tool" + +if [ "$home" = "" -o ! -d "$home/public_html" ]; then + echo "$1 does not have a public_html" >&2 + exit 1 +fi + +cat <<EOF >$runbase.conf~ +server.modules = ( + "mod_access", + "mod_accesslog", + "mod_alias", + "mod_compress", + "mod_redirect", + "mod_rewrite", + "mod_fastcgi", + "mod_cgi", +) + +server.port = $port +server.use-ipv6 = "disable" +server.username = "local-$tool" +server.groupname = "local-$tool" +server.core-files = "disable" +server.document-root = "$home/public_html" +server.pid-file = "$runbase.pid" +server.errorlog = "$home/error.log" +server.breakagelog = "$home/error.log" +server.follow-symlink = "enable" +server.max-connections = 20 +server.max-keep-alive-idle = 60 +server.max-worker = 5 +server.stat-cache-engine = "fam" +ssl.engine = "disable" + +alias.url = ( "/$tool" => "$home/public_html/" ) + +index-file.names = ( "index.php", "index.html", "index.htm" ) +dir-listing.encoding = "utf-8" +server.dir-listing = "disable" +url.access-deny = ( "~", ".inc" ) +static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" ) + +accesslog.use-syslog = "disable" +accesslog.filename = "$home/access.log" + +cgi.assign = ( + ".pl" => "/usr/bin/perl", + ".py" => "/usr/bin/python", + ".pyc" => "/usr/bin/python", +) + +fastcgi.server += ( ".php" => + (( + "bin-path" => "/usr/bin/php-cgi", + "socket" => "/tmp/php.socket.$tool", + "max-procs" => 1, + "bin-environment" => ( + "PHP_FCGI_CHILDREN" => "4", + "PHP_FCGI_MAX_REQUESTS" => "10000" + ), + "bin-copy-environment" => ( + "PATH", "SHELL", "USER" + ), + "broken-scriptfilename" => "enable" + )) +) + +EOF + +/usr/share/lighttpd/create-mime.assign.pl >>$runbase.conf~ +if [ -r $home/.lighttpd.conf ]; then + cat $home/.lighttpd.conf >>$runbase.conf~ +fi + +mv $runbase.conf~ $runbase.conf + +exec /usr/sbin/lighttpd -f $runbase.conf -D >>$home/error.log 2>&1 + diff --git a/modules/toollabs/files/portgrabber b/modules/toollabs/files/portgrabber new file mode 100755 index 0000000..b4d8baf --- /dev/null +++ b/modules/toollabs/files/portgrabber @@ -0,0 +1,30 @@ +#!/usr/bin/perl -w +# +# Copyright © 2013 Marc-André Pelletier <[email protected]> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +use Socket; + +my $tool = shift; +my $line; + +socket(SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!"; +connect(SOCK, sockaddr_un("/tmp/sock.portgranter")) || die "connect: $!"; +$| = 1; +syswrite SOCK, "$tool\n"; +my $port = 0+<SOCK>; + +exec @ARGV, $port; + diff --git a/modules/toollabs/files/portgranter b/modules/toollabs/files/portgranter new file mode 100755 index 0000000..11d356e --- /dev/null +++ b/modules/toollabs/files/portgranter @@ -0,0 +1,141 @@ +#!/usr/bin/perl -w +# +# Copyright © 2013 Marc-André Pelletier <[email protected]> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +use Socket; +use File::NFSLock; +use Fcntl qw(LOCK_EX LOCK_NB); + +my $scoreboard = "/tmp/dynamic"; +my $sockname = "/tmp/sock.portgranter"; +my $uaddr = sockaddr_un($sockname); + +unlink($sockname); +socket(Server, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!"; +bind (Server, $uaddr) || die "bind: $!"; +chmod 0666, $sockname; +listen(Server, SOMAXCONN) || die "listen: $!"; + +sub spawn { + my $sock = shift; + my $coderef = shift; + my $pid = fork(); + + if($pid>0 or not defined $pid) { + close $sock; + return $pid; + } + + exit($coderef->($sock)); +} + +my $hostname = `hostname`; chomp $hostname; +my %clients; +my @ports; +my $reap = 0; +my $update = 1; + +use POSIX ":sys_wait_h"; +sub REAPER { + $reap = 1; + $SIG{CHLD} = \&REAPER; # loathe SysV +} + +$SIG{CHLD} = \&REAPER; + + +for(my $i=4000; $i<5000; $i++) { + push @ports, $i; +} + +$| = 1; +for(;;) +{ + if($reap) { + $reap = 0; + my $child; + while( ($child = waitpid(-1, WNOHANG)) > 0 ) { + if(defined $clients{$child}) { + my $c = $clients{$child}; + delete $clients{$child}; + $update = 1; + unshift @ports, $c->{'port'}; + } + } + } + + if($update) { + if(my $lock = new File::NFSLock { + file => "$scoreboard.new", + lock_type => LOCK_EX, + blocking_timeout => 10, + stale_lock_timeout => 120, + }) { + my @scoreboard; + if(open SB, "<$scoreboard") { + while(<SB>) { + if(m/^\S+ ([^:]+):[0-9]+$/) { + next if $1 eq $hostname; + } + push @scoreboard, $_; + } + close SB; + } + foreach my $c (values %clients) { + push @scoreboard, "$c->{'tool'} $hostname:$c->{'port'}\n"; + } + + if(open SB, ">$scoreboard.new") { + print SB join '', @scoreboard; + if(rename "$scoreboard.new", $scoreboard) { + $update = 0; + } else { + unlink "$scoreboard.new"; + } + close SB; + } + } + } + + if($#ports < 0) { + sleep 1; + next; + } + + my $client; + next unless accept($client, Server); + + my $tool = <$client>; + my $port = shift @ports; + chomp $tool; + print $client "$port\n"; + + my $pid = spawn $client, sub { + my $sock = shift; + scalar <$sock>; + close $sock; + return 0; + }; + if(defined $pid) { + $clients{$pid} = { + pid => $pid, + tool => $tool, + port => $port, + }; + $update = 1; + } +} + diff --git a/modules/toollabs/files/portgranter.conf b/modules/toollabs/files/portgranter.conf new file mode 100644 index 0000000..5851a8d --- /dev/null +++ b/modules/toollabs/files/portgranter.conf @@ -0,0 +1,13 @@ +# portgranter - grant ports dynamically for daemons + +description "Portgranter" + +start on runlevel [2345] +stop on runlevel [!2345] + +respawn + +console log + +exec /usr/local/sbin/portgranter + diff --git a/modules/toollabs/files/tool-lighttpd b/modules/toollabs/files/tool-lighttpd index 309b481..357b2b0 100755 --- a/modules/toollabs/files/tool-lighttpd +++ b/modules/toollabs/files/tool-lighttpd @@ -15,137 +15,5 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -tool="$1" -user="local-$tool" -home=$(getent passwd $user | cut -d : -f 6 | sed -e 's/\/$//') -if [ "$(getent group $user | cut -d : -f 1)" != "$user" ]; then - echo "$0: $1 does not appear to be a tool" >&2 - exit 1 -fi -spool="/var/run/lighttpd" -runbase="$spool/$tool" -scoreboard="/data/project/.system/dynamic" - -if [ "$home" = "" -o ! -d "$home/public_html" ]; then - echo "$1 does not have a public_html" >&2 - exit 1 -fi - -export llock="/tmp/toollock.$tool" -export lock="/tmp/toollock.lock" - -trap "rm -f $llock" 0 -touch $llock -while [ -f $llock ]; do - mv -n $llock $lock - sleep 1 -done -trap "rm -f $lock $scoreboard.tmp" 0 -port=4000 -past="$(grep "^$tool " $scoreboard)" -if [ "$past" != "" ]; then - port=$(echo "$past" | sed -e 's/.*://') -fi -grep -v "^$tool " $scoreboard >$scoreboard.tmp -while grep -q ":$port$" $scoreboard.tmp; do - port=$[$port+1] -done -echo "$tool $(hostname):$port" >>$scoreboard.tmp -mv $scoreboard.tmp $scoreboard -rm -f $lock -trap "" 0 - -cat <<EOF >$runbase.conf~ -server.modules = ( - "mod_access", - "mod_accesslog", - "mod_alias", - "mod_compress", - "mod_redirect", - "mod_rewrite", - "mod_fastcgi", - "mod_cgi", -) - -server.port = $port -server.use-ipv6 = "disable" -server.username = "local-$tool" -server.groupname = "local-$tool" -server.core-files = "disable" -server.document-root = "$home/public_html" -server.pid-file = "$runbase.pid" -server.errorlog = "$home/error.log" -server.breakagelog = "$home/error.log" -server.follow-symlink = "enable" -server.max-connections = 20 -server.max-keep-alive-idle = 60 -server.max-worker = 5 -server.stat-cache-engine = "fam" -ssl.engine = "disable" - -alias.url = ( "/$tool" => "$home/public_html/" ) - -index-file.names = ( "index.php", "index.html", "index.htm" ) -dir-listing.encoding = "utf-8" -server.dir-listing = "disable" -url.access-deny = ( "~", ".inc" ) -static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" ) - -accesslog.use-syslog = "disable" -accesslog.filename = "$home/access.log" - -cgi.assign = ( - ".pl" => "/usr/bin/perl", - ".py" => "/usr/bin/python", - ".pyc" => "/usr/bin/python", -) - -fastcgi.server += ( ".php" => - (( - "bin-path" => "/usr/bin/php-cgi", - "socket" => "/tmp/php.socket.$tool", - "max-procs" => 1, - "bin-environment" => ( - "PHP_FCGI_CHILDREN" => "4", - "PHP_FCGI_MAX_REQUESTS" => "10000" - ), - "bin-copy-environment" => ( - "PATH", "SHELL", "USER" - ), - "broken-scriptfilename" => "enable" - )) -) - -EOF - -/usr/share/lighttpd/create-mime.assign.pl >>$runbase.conf~ -if [ -r $home/.lighttpd.conf ]; then - grep '^\s*server.dir_listing\s*=' $home/.lighttpd.conf >>$runbase.conf~ - sed -e 's/server\s*\./var./g' $home/.lighttpd.conf >>$runbase.conf~ -fi - -chown $user:$user $runbase.conf~ -mv $runbase.conf~ $runbase.conf - - -cleanup() { - trap "rm -f $llock" 0 - touch $llock - while [ -f $llock ]; do - mv -n $llock $lock - sleep 1 - done - trap "rm -f $lock $scoreboard.tmp" 0 - grep -v "^$tool " $scoreboard >$scoreboard.tmp - mv $scoreboard.tmp $scoreboard - rm -f $lock - trap "" 0 -} - -trap "cleanup;exit 0" 15 - -/bin/su -c "/usr/sbin/lighttpd -f $runbase.conf -D >>$home/error.log 2>&1" - "$user" -/bin/su -c "/bin/date >$home/lighttpd.STOPPED" - "$user" - -cleanup -exit 1 +tool=$(/usr/bin/id -nu|sed -e 's/^local-//') +exec /usr/local/sbin/portgrabber "$tool" /usr/local/sbin/lighttpd-starter "$tool" diff --git a/modules/toollabs/manifests/exec_environ.pp b/modules/toollabs/manifests/exec_environ.pp index 816a360..a4566ae 100644 --- a/modules/toollabs/manifests/exec_environ.pp +++ b/modules/toollabs/manifests/exec_environ.pp @@ -50,6 +50,7 @@ 'libdbi-perl', 'libdigest-crc-perl', 'libdigest-hmac-perl', + 'libfile-nfslock-perl', 'libhtml-html5-entities-perl', 'libhtml-parser-perl', 'libhttp-message-perl', diff --git a/modules/toollabs/manifests/webnode.pp b/modules/toollabs/manifests/webnode.pp index 6747b9b..56bd874 100644 --- a/modules/toollabs/manifests/webnode.pp +++ b/modules/toollabs/manifests/webnode.pp @@ -82,9 +82,41 @@ ensure => file, owner => 'root', group => 'root', - mode => '0755', + mode => '0555', source => "puppet:///modules/toollabs/tool-lighttpd", } + file { "/usr/local/sbin/lighttpd-starter": + ensure => file, + owner => 'root', + group => 'root', + mode => '0555', + source => "puppet:///modules/toollabs/lighttpd-starter", + } + + file { "/usr/local/sbin/portgrabber": + ensure => file, + owner => 'root', + group => 'root', + mode => '0555', + source => "puppet:///modules/toollabs/portgrabber", + } + + file { "/usr/local/sbin/portgranter": + ensure => file, + owner => 'root', + group => 'root', + mode => '0555', + source => "puppet:///modules/toollabs/portgranter", + } + + file { "/etc/init/portgranter.conf": + ensure => file, + owner => 'root', + group => 'root', + mode => '0444', + source => "puppet:///modules/toollabs/portgranter.conf", + } + } -- To view, visit https://gerrit.wikimedia.org/r/89416 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I3d55430f3df83644fa158d1f54654675e4d7ed95 Gerrit-PatchSet: 1 Gerrit-Project: operations/puppet Gerrit-Branch: production Gerrit-Owner: coren <[email protected]> Gerrit-Reviewer: coren <[email protected]> Gerrit-Reviewer: jenkins-bot _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
