--- projects/cms/source/host/ihost-perl/ihost.pl 2001/01/29 16:51:50 1.9 +++ projects/cms/source/host/ihost-perl/ihost.pl 2001/03/12 23:20:43 1.25 @@ -2,14 +2,15 @@ # ----------------------------------------------------------- # Perl i-scream Host. +# http://www.i-scream.org.uk # # An all-in-one script to act as an i-scream host on # a typical Unix/Linux box. You may adapt the data-gathering # methods as you see fit. # - pjm2@ukc.ac.uk # -# $Author: pjm2 $ -# $Id: ihost.pl,v 1.9 2001/01/29 16:51:50 pjm2 Exp $ +# $Author: tdb $ +# $Id: ihost.pl,v 1.25 2001/03/12 23:20:43 tdb Exp $ #------------------------------------------------------------ $| = 1; @@ -31,6 +32,8 @@ use vars qw ( $tcp_port $filter_addr $file_list + $fqdn + $pidfile ); if (@ARGV != 2) { @@ -42,6 +45,10 @@ $filter_manager_port = $ARGV[1]; $seq_no = 1; +# write our PID to a file +$pidfile = "ihost.pid"; +&write_pid(); + &tcp_configure(); &send_udp_packet(); @@ -69,19 +76,32 @@ while (1) { `sleep $delay`; } +# we'll probably never get here... +`rm -f $pidfile`; exit(0); + +#----------------------------------------------------------------------- +# tcp_configure +# Establishes a TCP connection to the specified i-scream filter manager. +# The host then requests details from the server, such as the intervals +# at which to send UDP packets. +#----------------------------------------------------------------------- sub tcp_configure() { my($sock) = new IO::Socket::INET( PeerAddr => $filter_manager_addr, PeerPort => $filter_manager_port, Proto => 'tcp' - ) or die "Could not perform configuration via TCP: $!\n"; + ) or die "Cannot connect!"; + if (!defined $sock) { + print "IHOST ERROR: Could not connect to $filter_manager_addr:$filter_manager_port.\n"; + print "Please check that there is an i-scream server at this address.\n"; + print "Program ended.\n"; + exit(1); + } - die "Could not connect to the i-scream filter manager: $!\n" unless $sock; - - # Now run through the configuration process. + # Now run through the configuration process... my($response); print $sock "STARTCONFIG\n"; @@ -107,6 +127,13 @@ sub tcp_configure() { print "File list obtained: $file_list\n"; + print $sock "FQDN\n"; + $response = <$sock>; + chop $response; + $fqdn = $response; + + print "FQDN returned: $fqdn\n"; + print $sock "UDPUpdateTime\n"; $response = <$sock>; chop $response; @@ -131,9 +158,17 @@ sub tcp_configure() { print $sock "FILTER\n"; $response = <$sock>; + unless (defined($response)) { + print "Failed: Could not get a filter address from the filter manager.\n"; + exit(1); + } chop $response; $response =~ /(.*);(.*);(.*)/; ($filter_addr, $udp_port, $tcp_port) = ($1, $2, $3); + unless (defined($filter_addr) && defined($udp_port) && defined($tcp_port)) { + print "Failed: Filter address response from server did not make sense: $response\n"; + exit(1); + } print "Got filter data ($filter_addr, $udp_port, $tcp_port)\n"; @@ -151,13 +186,24 @@ sub tcp_configure() { close($sock); print "Configuration finished sucessfully!\n"; + + return; } + + + +#----------------------------------------------------------------------- +# send_udp_packet +# Sends a UDP packet to an i-scream filter. +# The packet contains XML markup describing some of the machine's state. +# Receipt of UDP packets is not guaranteed. +#----------------------------------------------------------------------- sub send_udp_packet() { my(@statgrab) = `./statgrab.pl`; my(%packet); - for (my($i) = 0; $i < $#statgrab; $i++) { + for (my($i) = 0; $i <= $#statgrab; $i++) { $statgrab[$i] =~ /^([^\s]*) (.*)$/; $packet{$1} = $2; } @@ -167,29 +213,26 @@ sub send_udp_packet() { my($disk_info) = ""; my($i) = 0; while (defined $packet{"packet.disk.p$i.attributes.mount"}) { - $disk_info .= ""; - $disk_info .= qq/$packet{"packet.disk.p$i.attributes.name"}<\/name>/; - $disk_info .= qq/$packet{"packet.disk.p$i.attributes.kbytes"}<\/kbytes>/; - $disk_info .= qq/$packet{"packet.disk.p$i.attributes.used"}<\/used>/; - $disk_info .= qq/$packet{"packet.disk.p$i.attributes.avail"}<\/avail>/; - $disk_info .= qq/$packet{"packet.disk.p$i.attributes.mount"}<\/mount>/; - $disk_info .= ""; + $disk_info .= " + $packet{"packet.load.load1"} $packet{"packet.load.load5"} @@ -201,6 +244,7 @@ sub send_udp_packet() { $packet{"packet.os.platform"} $packet{"packet.os.sysname"} $packet{"packet.os.version"} + $packet{"packet.os.uptime"} $packet{"packet.users.count"} @@ -221,47 +265,61 @@ sub send_udp_packet() { $packet{"packet.cpu.swap"} - $packet{"packet.memory.real"} + $packet{"packet.memory.total"} $packet{"packet.memory.free"} - $packet{"packet.memory.swap_total"} - $packet{"packet.memory.swap_free"} + $packet{"packet.swap.total"} + $packet{"packet.swap.free"} $disk_info EOF + # Make the packet smaller by stripping out newlines and leading spaces. $xml =~ s/\n\s*//g; - + my($sock) = new IO::Socket::INET ( PeerPort => $udp_port, PeerAddr => $filter_addr, Proto => 'udp' - ) or die "Socket: $!\n"; + ) or die "Could not send UDP: $!\n"; print $sock $xml or die "Could not send UDP packet: $!\n"; close($sock); $seq_no++; print "-"; + + return; } + + + +#----------------------------------------------------------------------- +# send_tcp_heartbeat +# Establishes a TCP connection to an i-scream filter. +# The heartbeat is used as a guaranteed "I'm alive" delivery mechanism. +#----------------------------------------------------------------------- sub send_tcp_heartbeat() { my($sock) = new IO::Socket::INET( PeerAddr => $filter_addr, PeerPort => $tcp_port, Proto => 'tcp' - ) or die "Could not perform heartbeat via TCP: $!\n"; + ) or return; + if (!defined $sock) { + print "IHOST WARNING: Failed to deliver a heartbeat to the i-scream filter.\n"; + return; + } - die "Could not connect to the i-scream filter: $!\n" unless $sock; - # Now run through the configuration process. my($response); print $sock "HEARTBEAT\n"; $response = <$sock>; + return if (!defined $response); chop $response; if (!$response eq "OK") { close($sock); @@ -271,6 +329,7 @@ sub send_tcp_heartbeat() { print $sock "CONFIG\n"; $response = <$sock>; + return if (!defined $response); chop $response; if (!$response eq "OK") { close($sock); @@ -280,6 +339,7 @@ sub send_tcp_heartbeat() { print $sock "$file_list\n"; $response = <$sock>; + return if (!defined $response); chop $response; if (!$response eq "OK") { close($sock); @@ -289,6 +349,7 @@ sub send_tcp_heartbeat() { print $sock "$last_modified\n"; $response = <$sock>; + return if (!defined $response); chop $response; if ($response eq "ERROR") { close($sock); @@ -303,6 +364,7 @@ sub send_tcp_heartbeat() { print $sock "ENDHEARTBEAT\n"; $response = <$sock>; + return if (!defined $response); chop $response; if (!$response eq "OK") { close($sock); @@ -312,4 +374,19 @@ sub send_tcp_heartbeat() { close($sock); print "^"; + + return; +} + +#----------------------------------------------------------------------- +# write_pid +# Writes the PID (process ID) of this instance to $pidfile. +# This is then used by a seperate script to check (and restart) ihost. +#----------------------------------------------------------------------- +sub write_pid() { + open PID, ">$pidfile"; + print PID $$; + close PID; + + return; }