[Pkg-grid-commits] nws/debian nws.conf.example, NONE, 1.1 nws_setup, NONE, 1.1

Martin Quinson mquinson at alioth.debian.org
Mon Aug 8 20:03:20 UTC 2005


Update of /cvsroot/pkg-grid/nws/debian
In directory haydn:/tmp/cvs-serv23429

Added Files:
	nws.conf.example nws_setup 
Log Message:
don't maintain this as a patch anymore. Graziano don't seem to be willing integrating this, and it's a pain to modify

--- NEW FILE: nws.conf.example ---
# ConfFile for NWS - to be parsed by nws_setup
# (Written by Martin Quinson <mquinson at ens-lyon.fr>)
 
#########################
## Syntax of this file ##
#########################

#  - It is read by grepping
#    That mean you can write everything you want to in it. Just, if you want a variable set
#    in the launcher, follow this syntax: 
#
#                 '<no space><name of the variable>=<value>'
#
#    Every other lines are ignored, but I still mark my comments with '#'. 
#  - Don't quote the values. You can't even put ` ` parts, and ${name} parts :)
#  - If you want a particular value to be different for several machine, write :
#  
#        '<no space><name of the variable>(<name of the machine>)=<value>'
#
#    (name of the machine is: `hostname`.`domainname` if `domainname` is set.
#                             `hostname`              if not)
#    You can set the variable my_name, too, but only if `hostname` is broken, since 
#     it's an internal value, too.
#
#    different machines can even share the same value. Example:
#           sensor_cpu(fulbert,toto,gabuzomeu)=yes
#
#
# Values used:
#  Here are the ones mandatory:
#   part_to_run=list of the parts of nws to run on this host
#               authorized part name are : "nameserver memory sensor "
#               order is not important. I manage this :)
#   skills=list of the skills of the server to manage 
#   uid= the user ID to run under

##############################
## HOW TO USE NWS LOCALLY ? ## (for a single machine)
##############################

# The simplest possible configuration is to run everything locally. 
# To do that, you don't need to edit this file at all.

#############################################
## HOW TO USE NWS IN A MASTER/SLAVES WAY ? ## (for a single cluster platform)
#############################################

# For a single cluster, a master-slave schema can be used. The master node 
#  runs all administrativia process, and all others nodes (being "slave"s) use
#  these services on the master.
# To do that, edit this file, following the next 3 steps:

# STEP 1) 
# For a simple configuration, declare one of your machine as master, and all others as slave.
#  Ie, add the hostname of the slaves between parenthesis in the "group(blabla)=slave" line, and
#  same for master.
group(blaise)=slave
group(terminus)=master

# STEP 2)
# Then, you must tell which machine participate to the TCP monitoring experiment. Here, it is all
#  all hosts.
# To do that, list all machines on the skill.tcpMessageMonitor line with the syntax "member:$hostname"
#
#  Ie, you must list all participating machine, preceded by the string "member:"
skill.tcpMessageMonitor=member:terminus member:blaiAZEse

# STEP 3)
# Finally, you must tell the machines where the nameserver and the memory (ie database) server are.
# For that, just replace "terminus" by the hostname declared as master above.
# Be sure to also give the port on which the service run (8090 for nameserver and 8050 for memory unless you 
#  specified something else).
nameserver(slave)=terminus:8090
memory(slave)=terminus:8050

######################################
## HOW TO USE NWS IN A TREE MANER ? ## (for a multi-clusters platform)
######################################

# Each time an experiment is done, the sensors store the result in the memory, which can become a
#  bottleneck when the memory is far away from the sensors. To solve this, we put a memory host on
#  each platform, so that the memory and sensors keep close to each other.
# Another problem is that link experiments are not really scalable. To solve that, we do several link
#  experiments in a tree manner. On each clusters, all machines do a link experiment, and then, 
#  another experiment is done between leaders of each cliques. 
#  Then, to get the values between all pair of machines, even if no direct experiment exist between them, use FAST ;)

# To configure NWS that way, follow the next steps:

# STEP 1) Tell in which group are each machines
# STEP 1.a) Elect center and leaders
#  Elect one machine in the whole system as center, and elect on machine per cluster as leader
#  (each cluster need a leader, which can't be center at the same time)
group(popc1)=center
group(popc2,pom1)=leader

# STEP 1.b) Tell all other machines in which group they are
#  Declare one group per cluster, listing all machines between parenthesis
#  Don't list the center and the leaders here (or they will be in two groups ;).
group(popc3,popc4,popc5,popc6,popc7,popc8)=popc
group(pom2,pom3,pom4,pom5,pom6,pom7,pom8)=pom

# STEP 2) Declare the link experiments
#  List all the machines in the corresponding link experiment 
# STEP 2.a) One experiment per cluster. 
# The name of the cluster's leader (or center) comes between parenthesis, and all machines of this cluster comes after '=',
#  following the syntax "member:$hostname"
# The experiment must list center and leader also.
skill.tcpMessageMonitor(popc1)=member:popc1 member:popc2 member:popc3 member:popc4 member:popc5 member:popc6 member:popc7 member:popc8
skill.tcpMessageMonitor(pom1)= member:pom1  member:pom2  member:pom3  member:pom4  member:pom5  member:pom6  member:pom7  member:pom8

# STEP 2.b) One generic experiment between master and leaders
# Don't change what comes between parenthesis, but list all master and leaders after the '='.
skill.tcpMessageMonitor(center)=member:popc1 member:popc2 member:pom1

# STEP 3)
#  Declare where each host should look for the nameserver and for the memory server
#  In NWS, the nameserver must be uniq, and we declare one memory per cluster
#  We have to relist the center and leaders in the memory() lines between parenthesis, since they are not in
#   the plain cluster group (they are already in the 'center' or 'leader' groups)
memory(popc1,popc2,popc)=popc1:8050
memory(pom1,pom)=pom:8050

# Also uncomment the next line (it isn't done by default because it would interact with local and master/slave installs)
# nameserver=popc1:8090


# Remark: we have to distinguish between center and leader, so that we can run the global link experiment on the center
#  and the cluster specific one on the leader.

###################################
## NO NEED TO EDIT THE FOLLOWING ## (unless you want to write your config file from the scratch)
###################################

# By default, a machine is "master", so that everything runs locally
group=master

# Which processes to run on the different kind of hosts
part_to_run(master)=nameserver memory sensor 
part_to_run(slave)=                   sensor

part_to_run(center)=nameserver memory sensor 
part_to_run(leader)=           memory sensor 

# Which activities to run on the different kind of hosts
skills(master)=cpuMonitor memoryMonitor tcpMessageMonitor 
skills(slave)= cpuMonitor memoryMonitor

skills(center)=cpuMonitor memoryMonitor tcpMessageMonitor
skills(leader)=cpuMonitor memoryMonitor tcpMessageMonitor 

# Default args for the activities
skill.cpuMonitor=nice:0
skill.memoryMonitor=

--- NEW FILE: nws_setup ---
#! /usr/bin/perl -w
# My personal script to manage to NWS familly of daemons.
# Contrary to the upstream provided scripts, it does not
#  try to manage all the machines on the net. It only
#  manage the scripts on the locale machine, but it does
#  it well. It has a conffile (usually /etc/nws.conf),
#  in which you can set a great lot of things.
# To manage the whole net, it is easy to do scripts like
#  the next one to pass a command to each site :
#
#--BEGIN
##! /bin/sh
## To be run as cron table on only on machine
#
#machines="<space separed list of your machines>"
#for n in `echo $machines` ; do
#  cmd="rsh $n /path/to/nws_setup $@";
#  echo " $cmd";
#  system($cmd);
#  echo;
#done;
#--END
#
# Copyright (C) 1999 Free Software Foundation, Inc.
# Martin Quinson (martin.quinson::loria.fr), 2000,2001,2002,2005.
# Distributed under the GPL Licence. 
#

# TODO: 
#  - Searching the bin path after parsing the config file, we wouldn't 
#    have to hardcode the name of binaries
#  - What if all binaries are not in the same directory?
#  - for now, logpath and statpath are the first writable dir from 
#    hardcoded lists. Need for a better tests?
#  - Allow being in several groups
#  - check that handling of empty value in config file is correct
#  - generalize the skills

use strict;
use POSIX qw(setsid setuid); #to fork daemons
use IO::Handle; #just to flush...

my $conffile=""; # Where to read the args from
my $progname = $0; $progname= $& if $progname =~ m,[^/]+$,;

#
# Parse command line
#
my $verbose=0; # do I have to tell my life to user or should I shut up ?
my $gdb_attach=0;
my $whereconf="/etc/nws.conf $ENV{HOME}/.nws.conf $ENV{HOME}/etc/nws.conf /usr/local/etc/nws.conf";

my $opt;
for ($opt = shift @ARGV; $opt =~ /^--?(.*)$/; $opt = shift @ARGV) {
    my $optname = $1;
    if ($optname =~ /gdb/) {
	$gdb_attach = 1;
    } elsif ($optname =~ /verbose/ || $optname =~ /^v$/) {
	$verbose = 1;
    } elsif ($optname =~ /conffile/ || $optname =~ /^c$/) {
	$whereconf= shift @ARGV;
    }
}
unshift @ARGV,$opt;


#
# Search the conffile
# 
my $i;

foreach $i (split(/\s+/,$whereconf)) {
    if (("$conffile" eq "")&&(-s $i)) {
	$conffile=$i;
    }
}
if (-z "$conffile") {
    die ("$progname: Can't find my conffile ! I've searched in :\n  $whereconf\n  Please create one, or edit the script !\n");
}

sub empty {
    my $aze=shift;
    return 1 unless (defined $aze);
    return 1 unless ($aze =~ m,\S,);
    return 0;
}

#####################
# Read all the args #
#####################

# Who am I ?
my $hostname; # this machine
my $my_group=undef; # Group of which this machine is member
my $wanted_uid=""; # the user ID we should be running under

# Meta configuration
my ($possible_actions,$possible_infos,$possible_skills,
    $possible_parts,$possible_stop);
my %howto; # $howto{cat}{part} is the cmd to exec to $cat'ing $part
           #  Valid value to cat are: start, stop and test
my %skills; # keys=name of skills to run;values=args for them FIXME?

# Content of config file
my %config; # actual value of each variable


# What should I do here ?
my $start_part; # ordoned list of parts to start
my $stop_part; # idem, to stop

# FIXME: Old cruft ? 
# my $ctrl_host; #the prog to check the daemons
my $start_activity; #the prog to check the skills


##
## Get a variable from the configuration file, or from the provided
##  defaults. Defaults may content several possibilities, separated by '||'
##  Each part can be '$ENV{"something"}' or a fixed string.
##
sub arg {
    my $name=shift;
    my $defaults=shift;

    my $line; # to read the conffile

    my $global=undef; # where to put any global corresponding
    my $group=undef;  # where to put setting for my group
    my $partic=undef; # where to put any setting for this particular machine
    my $res;
    
    ##
    ## Parse conf file
    ## 
    open FILE,"$conffile" ||
	die "$progname: Error: can't open the conffile `$conffile'\n";
    while (<FILE>) {
	chomp;
	while ((s/\\$//) && ($_ .= <FILE>)){}
	s/#.*$//;
	next unless /^$name/;
	chomp;
	if (/^$name\s*\(.*?$hostname[^\)]*\)\s*=\s*(.*?)\s*$/) {
	    warn "$progname: Warning: `$name' is set several times for $hostname in `$conffile'\n" 
		if (defined $partic);
	    $partic=$1;
	}
	if (defined $my_group && $my_group && 
	    /^$name\s*\(.*?$my_group[^\)]*\)\s*=\s*(.*?)\s*$/) {
	    warn "$progname: Warning: `$name' is set several times for group $my_group in `$conffile'\n" 
		if (defined $group);
	    $group=$1;
	}
	if (/^$name\s*=\s*(.*?)\s*$/) {
	    warn "$progname: Warning: `$name' is set several times in `$conffile'\n"
		if (defined $global);
	    $global=$1;
	}
    }
    close FILE;
    ##
    ## Get value from what was parsed if possible
    ##
    $res=$partic;
    $res=$group unless (defined $res);
    $res=$global unless (defined $res);

    ## 
    ## Handle defaults
    ##
    if ($defaults) {
	foreach my $defaultpart (split(/\|\|/,$defaults)) {
	    unless (defined($res)) {
		if ($defaultpart =~ /\$ENV\{([^\}]*)\}/) {
		    $res=$ENV{$1} || undef;
		} else {
		    $res=$defaultpart;
		}
	    }
	}
    }
    
    if ($res) {
	my $home="$ENV{HOME}";
	$res =~ s/^~\//$home/;
    }
    return $res;
}


#########################################
### the main function to get the args ###
#########################################
sub read_all_the_args {
    my $dol='$'; # to ease some regular expressions

    ##
    ## Parse the meta-configuration (at the end of this file):
    ##  definition of NWS parts and how to run them 
    ##

    my %legal_data_value; # what value can be found in the data part
    my %var_defaults; # defaults of each variable

    while (<DATA>) {
	chomp;
	while ((s/\\$//) && ($_ .= <DATA>) && chomp){}
	s/#.*$//;
	next if /^$/;
	die "unparsable metaconfiguration data: $_" 
	    unless (m/^(([^=[:blank:]])*)\s*?=\s*(.*)$/);
	my ($var,$val)=($1,$3);
	# Get info about what is allowed in the rest
	if      ($var =~ /^possible_parts$/) { $possible_parts  = $val;
	} elsif ($var =~ /^possible_stop$/) {  $possible_stop   = $val;
        } elsif ($var =~ /^possible_skills/) { $possible_skills = $val;
        } elsif ($var =~ /^possible_actions/) {$possible_actions= $val;
        } elsif ($var =~ /^possible_infos/) {  $possible_infos  = $val;

        # learn how to handle all parts, and which variables are needed for
        #   that (no other variable will be allowed in config file)
        } elsif ($var =~ /^([^_]*)_(.*)$/ 
		 && (grep {$_ eq $1} split(/ /,$possible_actions))
		 && (grep {$_ eq $2} split(/ /,$possible_parts))) {
	    $howto{$1}{$2}="$val";
	    foreach (split(/ +/,$val)) {
		while (s/^([^$dol]*\$)//) {
		    s/([-_a-zA-Z0-9]*)//;
		    $legal_data_value{$1}=1;
		}
 	    }

	# learn about infos on parts, and which variables are needed for
        #   that (no other variable will be allowed in config file)
        } elsif ($var =~ /^([^_]*)_(.*)$/ 
		 && (grep {$_ eq $1} split(/ /,$possible_parts))
		 && (grep {$_ eq $2} split(/ /,$possible_infos))) {
	    $legal_data_value{$var}=1; # these are always legal
	    $var_defaults{$var}=$val;
	    
	} elsif ($legal_data_value{$var}) {
	    $var_defaults{$var}=$val;
	} else {
	    print "Unparsable metaconfig line: $var=$val\n";
	}
    } 

    ##
    ## search the hostname
    ##

    my $host=`hostname`;
    chomp($host);
    # search the good domainname executable
    my $domainname="";
    if ((-f "/usr/bin/domainname")
	&& system("/usr/bin/domainname 2>&1 >/dev/null")) {
	$domainname="/usr/bin/domainname";
    } elsif ((-f "/bin/dnsdomainname")
	     && system("/bin/dnsdomainname 2>&1 >/dev/null")) {
	$domainname="/bin/dnsdomainname";
    } else {
	warn "Warning : unable to find the domainname\n" if $verbose;
    }
    if ("$domainname" ne "") {
	$hostname=`$domainname 2>/dev/null`;
	if ("$hostname" eq "") {
	    $hostname="$host";
	} else {
	    $hostname="$host.$hostname";
	}
    } else {
	$hostname="$host";
    }
    chomp($hostname);
    my $old_name = $hostname;
    # Get the verbosity from the config file
    $verbose ||= arg("verbose","0");
    $hostname=arg("hostname","$hostname");
    if ($hostname eq $old_name) {
	warn("DEBUG: My name is $hostname\n") if $verbose;
    } else {
	warn("My name is $hostname (was $old_name)\n") if $verbose;
    }
    $config{'hostname'}="$hostname";

    ##
    ## Drop priviledges as soon as possible
    ##
    $wanted_uid=arg("uid") || "";
    if (length($wanted_uid)) {
       POSIX::setuid($wanted_uid) || die "Cannot setuid($wanted_uid). Either run this as root or remove the uid configuration variable";
    }

    ##
    ## Am I member of a group ?
    ## 
    $my_group=arg("group") || "";    

    ##
    ## Search the bin path 
    ##
    my $bin_path="";
    foreach my $pathpart (split(':',$ENV{PATH})) {
	if (-x "$pathpart/nws_sensor" &&
	    -x "$pathpart/nws_nameserver" &&
	    -x "$pathpart/nws_memory" &&
	    -x "$pathpart/nws_ctrl" &&
	    (-x "$pathpart/nws_start_activity"|| -x "$pathpart/start_activity")) {
	    $bin_path=$pathpart;
	    last;
	} 
    }
    unless ($bin_path =~ /\W/) {
	die "Unable to find the nws binaries in your PATH. Please fix it.\n";
    }
    $config{'bin_path'}="$bin_path";
    
    # 
    # Search the log path
    #
    my $log_path="";
    my $path_test=(arg("log_path")||"")." /var/log/nws $ENV{HOME}/var/log/nws $ENV{HOME}/var/log/ /tmp";
    LOGPATH: foreach my $pathpart (split(" ",$path_test)) {
	if (-w "$pathpart") {
	    $log_path=$pathpart;
	    last;
	}
    }
    if (-z $log_path) {
	die "Unable to write logs to either $path_test. Please fix it\n";
    }
    $config{'log_path'}="$log_path";

    #
    # Search the state path
    #
    my $state_path="";
    $path_test=(arg("state_path")||"")." /var/state/nws $ENV{HOME}/var/state/nws $ENV{HOME}/var/state $log_path /tmp";
    LOGPATH: foreach my $pathpart (split(" ",$path_test)) {
	if (-w "$pathpart") {
	    $state_path=$pathpart;
	    last;
	}
    }
    if (-z $state_path) {
	die "Unable to write stat to either $path_test. Please fix it\n";
    }
    $config{'state_path'}="$state_path";

    # The rest is to ensure compatibility with upstream binaries 
    #  whose name where not prefixed with 'nws_' by me.
    if (-x "$bin_path/nws_start_activity") {
	$start_activity="$bin_path/nws_start_activity";
    } else { # must exist since we tested it for bin_path
	$start_activity="$bin_path/start_activity";
    }

    ##
    ## And now, read the args for all parts
    ##  We search in the config file, and what we search was parsed from
    ##  the end of this file.
    ##
    foreach my $var (sort keys %legal_data_value) {
#	printf "var=%s ; defaults=%s ; preset value=%s\n",
#  	  ($var ? $var:"UNDEF"),
#	  ($var_defaults{$var} ? $var_defaults{$var}:"UNDEF"),
#	  ($config{$var} ? $config{$var} : "UNDEF");
	$config{$var}=arg($var,$var_defaults{$var})
	    unless (defined $config{$var});
    }
#    foreach my $var (sort keys %config) {
#	print "$var=".($config{$var}||"***** UNDEF *****")."\n";
#    }

    ## 
    ## Ok, we can now rewrite the variables, to remove all reference to 
    ##  other variables in variable body ($a=AZE;$b=$a.$a)->($a=AZE;$b=AZE.AZE)
    ##
    my $errmsg_undef = "Error: '%s' is undef. The config file must provide a value.\n";

    foreach my $var (sort keys %config) {
	my $dol = '$';
#	print STDERR "Look at $var=".($config{$var}||"***** UNDEF *****")."\n";
	die sprintf ($errmsg_undef,$var) unless (defined $config{$var});
	while ($config{$var} =~ m/^([^$dol]*?)\$([-_a-zA-Z0-9]*)(.*)$/) {
	    die sprintf ($errmsg_undef,$2) unless (defined $config{$2} || length($2)==0);
	    $config{$var} = $1.(length($2)?$config{$2}:"").$3;
	}
    }
    
    ##
    ## Rewrite start, test, stop command lines.
    ## 
    foreach my $part (split(/ /,$possible_parts)) {
	foreach my $cat (split(/ /,$possible_actions)) {
	    die "Error in meta-configuration: Dunno how to $cat $part\n"
		unless ($howto{$cat}{$part});
	    while ($howto{$cat}{$part} =~ m/^([^$dol]*?)\$([-_a-zA-Z0-9]*)(.*)$/) {
		die sprintf ($errmsg_undef,$2) unless (defined $config{$2});
		$howto{$cat}{$part} = $1.$config{$2}.$3;
	    }	    
	}
    }
    ##
    ## Check that all info is defined
    ##
    foreach my $part (split(/ /,$possible_parts)) {
	foreach my $info (split(/ /,$possible_infos)) {
	    warn "Error in meta-configuration: info '$info' not present for '$part'.\n"
		unless defined $config{$part.'_'.$info};
	}
    }
    ##
    ## Read the args about the skills
    ##

    # read it
    my $skills=arg("skills");

    # verify it
    if (defined $skills) {
	foreach my $j (split(/\s+/,$skills)) {
	    my $good="no";
	    foreach $i (split(/\s+/,$possible_skills)) {
		$good="yes" if ($i eq $j);
	    }
	    ($good eq "yes") || 
		die "$progname: Error: Skill `$j' unknown.\n";
	    
	    # read the args of skills
	    $skills{$j}=arg("skill.$j");
	    unless (defined $skills{$j}) {
		$skills{$j}="";
	    }
#	printf "args of $j=${skills{$j}}\n";
	}
    }
}

#
# read and verify part_to_run
#

sub verify_part {
    #read it
    my $part_to_run=shift;
    $part_to_run=arg("part_to_run") unless (defined($part_to_run));

    die "Nothing to do (part_to_run is empty)\n"
	unless (defined($part_to_run) && $part_to_run);
    #verify it
    foreach my $j (split(/\s+/,$part_to_run)) {
	my $good="no";
	foreach $i (split(/\s+/,$possible_parts)) {
	    $good="yes" if ($j =~ /^$i(:[0-9]*)?$/);
	}
	($good eq "yes") || 
	    die "$progname: Error: I don't know the part `$j' of NWS.\n";
    }

    # sort it
    $start_part="";
    foreach $i (split(/\s+/,$possible_parts)) {
	$start_part="$start_part $1" if ($part_to_run=~ m,($i(:[0-9]*)?),);
    }

    $stop_part="";
    foreach $i (split(/\s+/,$possible_stop)) {
	$stop_part="$stop_part $1" if ($part_to_run=~ m,($i(:[0-9]*)?),);
    }    

    # trim it
    $start_part=~ s/^\s*(.*?)\s*$/$1/;
    $stop_part=~ s/^\s*(.*?)\s*$/$1/;
}

sub launch_skills {
    my $cmd;
    return 0 unless ($start_part =~ m,sensor,);
    sleep(5); # Make sure the sensor had enough time to start
    SKILL: foreach my $i (sort keys %skills) {
#	printf "  (re)launch the $i skill: ";
#	$cmd="$start_activity -F start $name{sensor} $i ${skills{$i}} ";
	$cmd="$start_activity -F $config{sensor_name} skillName:$i ${skills{$i}} ";
#	printf ("\n(Launch the skill with `$cmd')\n");
	if (system($cmd)){
	    # system returns "does something go wrong ?"
#	    if (system("$start_activity restart $name{sensor} $i ${skills{$i}} 1>/dev/null")) {
		printf "failed.\n";
		next SKILL;
#	    }
	}
#	printf "done.\n";
    }
}

sub fork_and_exec {
    my $cmd=shift;
    my $pid=fork;
    (defined $pid) || printf "Can't fork: $!\n";
    if ($pid) {
	#father
	printf("Forked to exec '$cmd'\n") if $verbose;
	if ($gdb_attach) {
	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid || die "Can't start a new session: $!";
	exec split(' ',$cmd);
    }
}

sub test {
    my $part=shift;

    my $res=qx,$howto{'test'}{$part},;
    chomp($res);
    $res=~ s/^.*?\s(\S*)$/$1/;
    return $res;
}

sub usage {
    die "$progname: Usage:  $progname [<options>] <command> [<part>]\n".
	"  where <command> is one of the following (unquoted):\n".
	"   'config' : display the configuration of this machine\n".
	"   'revive': Test if the daemons are dead, and try to launch them if needed.\n".
	"   'start': do not test anything, just try to launch the daemons.\n".
	"   'stop': Ask the daemon to die.\n".
	"   'restart': Synonym for 'stop' and then 'start'\n".
	"   'term': send SIGTERM to the daemon (which must be yours,\n".
	"                           unless you're root).\n".
	"   'kill': send SIGKILL to the daemon (which must be yours,\n".
	"                           unless you're root).\n".
        "   'test': display the state of the daemons.\n".
	"  if <part> is given, only applies to this part. It can be a *quoted* spaces separed list.\n".
	"    Autorized values : ".($possible_parts||"")."\n".
        "  <options> can be:\n".
        "    --conffile, -c\n".
        "           Use the given file as conffile\n".
        "    --gdb  When used in conjonction with 'start', only the first process will be launched, and\n".
        "           a gdb session will be attached to it\n".
        "    --verbose, -v\n".
        "           Run in verbose mode\n";
      
}

my $cmd = shift;
(defined $cmd) || usage;

read_all_the_args();
verify_part(shift);

my $pid; # to fork
my $status;

STDOUT->autoflush(1);


SWITCH: {
    #
    # config command
    #
    if ($cmd eq 'config') {
	my $err=0;
	print "Used configuration file: $conffile\n";
	print "Path to binaries used: '".$config{'bin_path'}."'\n";
	if (length($wanted_uid)) {
	    print "UID we should be running under:: $wanted_uid\n";
	} else {
	    print "We were not asked to change the UID before running (see 'uid' configuration variable)\n";
	}
    	print "This machine is named '$hostname'";
	if ($my_group) {
	    print ", and belongs to group '$my_group'\n";
	} else {
	    print ", and don't belong to any group.\n";
	}
	
	print "\nParts to run:\n $start_part (out of: $possible_parts)\n";
	foreach my $part(split(/ /,$possible_parts)) {
	    foreach my $cat (split(/ /,$possible_actions)) {
		my $cmd=$howto{$cat}{$part};
		$cmd =~ s/\s+/ /g;
		print "  Cmd to $cat a $part: '$cmd'\n";
	    }
	    print "\n";
	}
	my $skills=arg("skills");
	print "Skills to use:\n $skills (out of: $possible_skills)\n";
	$skills =~ s/ //g;
	if ($skills ne '' && !($start_part =~ /sensor/)) {
	    print "*** ERROR: Requested to run skills without sensor ***\n";
	    $err++;
	}
	print "\n";
	
	foreach my $servername (qw(nameserver memory)) {
	    my $server = $config{"$servername"};
	    $server =~ s/:.*//;
	    print "Check whether the $servername (on $server) is routable: ";
	    my $out = `ping -c 1 $server 2>&1`;
	    if ($? >> 8) {
		print "no !!\n*** ERROR: This machine cannot connect to the $servername ***\n";
		print "====[ 'ping -c 1 $server' output begin ]====\n$out\n====[ 'ping  -c 1 $server' output end ]====\n";
		print "You cannot use NWS without first fixing /etc/hosts (or equivalent).\n";
		$err++;
	    } else {
		print "yes.\n";
	    }
	}
	my $server = $config{"hostname"};
	print "Check whether it is possible to contact this machine from itself: ";
	my $out = `ping -c 1 $hostname 2>&1`;
	if ($? >> 8) {
		print "no !!\n*** ERROR: This machine cannot connect to itself ***\n";
		print "====[ 'ping -c 1 $server' output begin ]====\n$out\n====[ 'ping  -c 1 $server' output end ]====\n";
		print "You cannot use NWS without first fixing /etc/hosts (or equivalent).\n";
		$err++;
	} else {
		print "yes.\n";
	}
	if ($err) {
	    die "\n*** $err ERROR".($err>1?"S WERE":" WAS")." DETECTED ***\n";
	}
	last SWITCH;
    }
    #
    # Test command
    #
    if ($cmd eq "test") {
	printf "Testing NWS on $hostname:\n",;
	foreach $i (split(/\s+/,$start_part)) {
	    print "  Testing the NWS $i on ".$config{$i.'_name'}.": ";
	    print test($i).".\n";
	}
	last SWITCH;
    }
    #
    # Start command
    #
    if ($cmd eq "start") {
	printf "Starting the NWS family on $hostname:";
	foreach $i (split(/\s+/,$start_part)) {
	    printf " $i";
	    fork_and_exec($howto{'start'}{$i});
	}
	printf ".\n";
	launch_skills;
	last SWITCH;
    }
    #
    # log control
    #
    if ($cmd eq "log") {
	print "Toggle the NWS log production on $hostname:";
	foreach $i (split(/\s+/,$stop_part)) {
	    fork_and_exec($howto{'log'}{$i});
	    print " $i";
	}
	print ".\n";
	last SWITCH;
    }
    #
    # revive
    #
    if ($cmd eq "revive") {
	printf "Reviving the NWS family on $hostname:";
	PART: foreach $i (split(/\s+/,$start_part)) {
	    printf " $i";
	    $status=test($i);
	    if ($status eq "healthy") {
		print "(ok)";
		next PART;
	    } else {
		print "($status->" if $verbose;
		if ($status ne "dead") {
		    qx,$howto{'stop'}{$i},;
		}
		fork_and_exec($howto{'start'}{$i});
		WAIT: for (my $j=0;$j<10;$j++){
		    $status=test($i);
		    sleep 1; #waiting a while before testing it...
		    last WAIT if ($status eq "healthy");
		    print "." if $verbose;
		}
		print "$status)" if $verbose;
                print "($status)" unless $verbose;
	     }
	}
	print ".\n";
	launch_skills;
	last SWITCH;
    }
    #
    # Stop commands
    #
    if ($cmd eq "stop") {
	printf "Stopping the NWS family on $hostname:";
	foreach $i (split(/\s+/,$stop_part)) {
	    printf " $i";
	  WAIT: for (my $j=0;$j<10;$j++){
	      qx,$howto{"stop"}{$i},;
	      $status=test($i);
	      last WAIT if ($status eq "dead");
	      printf "." if $verbose;
	      sleep 1;
	  }
	}
	print ".\n";
	last SWITCH;
    }
    if ($cmd =~ m,term,) {
	printf "Sending the TERM signal to the NWS familly on $hostname:";
	foreach $i (split(/\s+/,$stop_part)) {
	    printf " $i";
	    if (-e $config{$i.'_pidfile'}) {
		my $pid=`cat $config{$i.'_pidfile'}`;
		chomp $pid;
		system("kill -TERM $pid");
	    } else {
		print "(pidfile not found)";
	    }
	}
	printf ".\n";
	last SWITCH;
    }
    if ($cmd =~ m,kill,) {
	printf "Sending the KILL signal to the NWS familly on $hostname:";
	foreach $i (split(/\s+/,$stop_part)) {
	    printf " $i";
	    if (-e $config{$i.'_pidfile'}) {
		my $pid=`cat $config{$i.'_pidfile'}`;
		chomp $pid;
		system("kill -KILL $pid");
		unlink($config{$i.'_pidfile'});
	    } else {
		print "(pidfile not found)";
	    }
	}
	printf ".\n";
	last SWITCH;
    }
    # 
    # Restart commands
    #
    if (($cmd eq "restart")||($cmd eq "cycle")) {
	system("$0 stop \"$start_part\"");
	printf("  (Waiting every part of NWS to stop...") if $verbose;
      WAIT: for (my $j=0;$j<10;$j++){
	  foreach $i (split(/\s+/,$start_part)){
	      $status=qx,$howto{"test"}{$i},;
	      if ($status eq "healthy") {
		  printf "." if $verbose;
		  sleep (1);
		  next WAIT;
	      }
	  }
	  printf " Done).\n" if $verbose;
	  last WAIT;
	  printf (".") if $verbose;
      }
	system("$0 start \"$stop_part\"");
	last SWITCH;
    }
    usage();
}

exit 0;

__DATA__
##
## This is the meta configuration
##  Warning: this is NOT perl. No ';' needed
##
possible_actions=start test stop log
possible_infos=name pidfile
# which process are runnable ?
possible_parts=nameserver memory sensor #in order of launching
possible_stop= sensor memory nameserver #in order of stoping
possible_skills=tcpMessageMonitor tcpConnectMonitor cpuMonitor memoryMonitor diskMonitor

# command line to start,test,stop each process
start_nameserver=$nameserver_bin -p $nameserver_port -v 5 \
                 -e $nameserver_errfile -l $nameserver_logfile -i $nameserver_pidfile \
                 -f $nameserver_state -c $nameserver_expire \
                  1>>$nameserver_logfile 2>>$nameserver_errfile
test_nameserver=$nws_cmd -t 3 test $nameserver_name:$nameserver_port
stop_nameserver=$nws_ctrl -t 3 halt $nameserver_name:$nameserver_port
log_nameserver=$nws_ctrl -t 3 log $nameserver_name:$nameserver_port

start_memory=$memory_bin -N $nameserver -v 5 \
             -p $memory_port -d $memory_state -s $memory_size \
             -e $memory_errfile -l $memory_logfile -i $memory_pidfile 1>>$memory_logfile 2>>$memory_errfile
test_memory=$nws_cmd -t 3 test $memory_name:$memory_port
stop_memory=$nws_ctrl -t 3 halt $memory_name:$memory_port
log_memory=$nws_ctrl -t 3 log $memory_name:$memory_port

start_sensor=$sensor_bin -N $nameserver -M $memory -v 5 \
             -p $sensor_port -c $sensor_cpu \
             -e $sensor_errfile -l $sensor_logfile -i $sensor_pidfile 1>>$sensor_logfile 2>>$sensor_errfile
test_sensor=$nws_cmd -t 3 test $hostname:$sensor_port
stop_sensor=$nws_ctrl -t 3 halt $hostname:$sensor_port
log_sensor=$nws_ctrl -t 3 log $hostname:$sensor_port

## default values about processes (should correspond to the cmd line args above)
# (globals)
nameserver=$ENV{NAME_SERVER}||$hostname:$nameserver_port
memory=$hostname:$memory_port

# (info about all part)
nameserver_bin=$bin_path/nws_nameserver
nameserver_port=$ENV{NAME_SERVER_PORT}||8090
nameserver_state=$state_path/nameserver.$hostname.$nameserver_port.registrations
nameserver_expire=3600

nameserver_name=$hostname:$nameserver_port
nameserver_errfile=$log_path/nameserver.$hostname.err
nameserver_logfile=$log_path/nameserver.$hostname.log
nameserver_pidfile=$state_path/nameserver.$hostname.pid


nws_ctrl=$bin_path/nws_ctrl
nws_cmd=$bin_path/nws_cmd

memory_bin=$bin_path/nws_memory
memory_port=$ENV{MEMORY_PORT}||8050
memory_state=$ENV{MEMORY_DIR}||$state_path/memory.$hostname.$memory_port
memory_size=$ENV{MEMORY_SIZE}||2000

memory_name=$hostname:$memory_port
memory_errfile=$log_path/memory.$hostname.$memory_port.err
memory_logfile=$log_path/memory.$hostname.$memory_port.log
memory_pidfile=$state_path/memory.$hostname.$memory_port.pid



sensor_bin=$bin_path/nws_sensor
sensor_port=$ENV{SENSOR_PORT}||8060
sensor_cpu=no

sensor_name=$hostname:$sensor_port
sensor_errfile=$log_path/sensor.$hostname.$sensor_port.err
sensor_logfile=$log_path/sensor.$hostname.$sensor_port.log
sensor_pidfile=$state_path/sensor.$hostname.$sensor_port.pid






More information about the Pkg-grid-commits mailing list