From 3e60f1512669ca15eb7aa131cbbdfb64ff597778 Mon Sep 17 00:00:00 2001
From: linggao <linggao@8638fb3e-16cb-4fca-ae20-7b5d299a9bcd>
Date: Thu, 24 Apr 2008 18:08:41 +0000
Subject: [PATCH] hierarchy support in conserver.pm

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@1193 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
---
 xCAT-server-2.0/lib/xcat/plugins/conserver.pm | 231 +++++++++++++++++-
 xCAT-server-2.0/sbin/xcatd                    |   1 +
 2 files changed, 223 insertions(+), 9 deletions(-)

diff --git a/xCAT-server-2.0/lib/xcat/plugins/conserver.pm b/xCAT-server-2.0/lib/xcat/plugins/conserver.pm
index 6899d0a13..d730a59a7 100644
--- a/xCAT-server-2.0/lib/xcat/plugins/conserver.pm
+++ b/xCAT-server-2.0/lib/xcat/plugins/conserver.pm
@@ -2,17 +2,146 @@
 #TODO: delete entries not being refreshed if no noderange
 package xCAT_plugin::conserver;
 use xCAT::Table;
+use xCAT::Utils;
+use Getopt::Long;
+use Sys::Hostname;
+
 use strict;
 use Data::Dumper;
 my @cservers = qw(mrv cyclades);
 my %termservers; #list of noted termservers
 
+my $usage_string=
+"  makeconservercf noderange
+  makeconservercf [-l|--local]
+  makeconservercf -h|--help 
+  makeconservercf -v|--version
+    -l|--local   The conserver gets set up only on the local host.
+                 The default goes down to all the conservers on 
+                 the server nodes and set them up.
+    -h|--help    Display this usage statement.
+    -v|--version Display the version number.";
+
+my $version_string="Version 2.0";
+
 sub handled_commands {
+  # setup the conserver.cf when xcatd on the service node starts the first time
+  # make sure cnserver is up and running when xcatd starts on the service node 
+  enableConsOnSN();
+
   return {
     makeconservercf => "conserver"
   }
 }
 
+sub preprocess_request { 
+  my $request = shift;
+  if ($request->{_xcatdest}) { return [$request]; }    #exit if preprocessed
+  my $callback=shift;
+  my @requests;
+  my $noderange = $request->{node}; #Should be arrayref
+
+  #display usage statement if -h 
+  my $extrargs = $request->{arg};
+  my @exargs=($request->{arg});
+  if (ref($extrargs)) {
+    @exargs=@$extrargs;
+  }
+  @ARGV=@exargs;
+
+  my $isSN=xCAT::Utils->isServiceNode();
+  my @hostinfo=xCAT::Utils->determinehostname();
+  my %iphash=();
+  foreach(@hostinfo) { $iphash{$_}=1;}
+
+  $Getopt::Long::ignorecase=0;
+  #$Getopt::Long::pass_through=1;
+  if(!GetOptions(
+      'l|local'     => \$::LOCAL,
+      'h|help'     => \$::HELP,
+      'v|version'  => \$::VERSION)) {
+    $request = {};
+    return;
+  }
+  if ($::HELP) {  
+    $callback->({data=>$usage_string});
+    $request = {};
+    return;
+  }
+  if ($::VERSION) { 
+    $callback->({data=>$version_string});
+    $request = {};
+    return;
+  }
+  if ($::LOCAL) {
+    if ($noderange && @$noderange>0) {
+      $callback->({data=>"Invalide option -l or --local when there are nodes specofied."});
+      $request = {};
+      return;
+    }
+  }
+ 
+  # get site master
+  my $master=xCAT::Utils->get_site_Master();
+  if (!$master) { $master=hostname(); }
+
+  # get conserver for each node
+  my %cons_hash=();
+  my $hmtab = xCAT::Table->new('nodehm');
+  my @items;
+  my $allnodes=1;
+  if ($noderange && @$noderange>0) {
+    $allnodes=0;
+    foreach my $node (@$noderange) {
+      my $ent=$hmtab->getNodeAttribs($node,['node', 'conserver']);
+      push @items,$ent; 
+    }
+  } else {
+    $allnodes=1;
+    @items = $hmtab->getAllNodeAttribs(['node', 'conserver']);
+  }
+
+  my @nodes=();
+  foreach (@items) {
+    if (defined($_->{conserver})) { push @{$cons_hash{$_->{conserver}}{nodes}}, $_->{node};}
+    else { push @{$cons_hash{$master}{nodes}}, $_->{node};}
+    push @nodes,$_->{node};
+  }
+
+  #send all nodes to the MN
+  if (!$isSN) { #
+    my $reqcopy = {%$request};
+    $reqcopy->{'_xcatdest'} = $master;
+    $reqcopy->{'_allnodes'} = $allnodes; # the original command comes with nodes or not
+    if ($allnodes==1) { @nodes=(); }
+    $reqcopy->{node} = \@nodes; 
+    push @requests, $reqcopy;
+    if ($::LOCAL) { return \@requests; } 
+  } 
+ 
+  # send to SN 
+  foreach my $cons (keys %cons_hash) {
+    #print "cons=$cons\n";
+    my $doit=0; 
+    if ($isSN) {
+      if (exists($iphash{$cons})) { $doit=1; }
+    } else {
+      if (!exists($iphash{$cons})) { $doit=1; }
+    }
+    
+    if ($doit) {
+      my $reqcopy = {%$request};
+      $reqcopy->{'_xcatdest'} = $cons;
+      $reqcopy->{'_allnodes'} = $allnodes; # the original command comes with nodes or not
+      $reqcopy->{node} = $cons_hash{$cons}{nodes};
+      my $no=$reqcopy->{node};
+      #print "node=@$no\n";
+      push @requests, $reqcopy;
+    }
+  } 
+  return \@requests;
+}
+
 sub process_request {
   my $req = shift;
   my $cb = shift;
@@ -43,10 +172,13 @@ sub docfheaders {
     push @$content,"default mrv { type host; portbase 2000; portinc 100; }\n"
   }
   unless (grep(/^access \*/,@meat)) {
-#TODO: something intelligent, allowing other hosts in
     #push @$content,"#xCAT BEGIN ACCESS\n";
     push @$content,"access * {\n";
     push @$content,"  trusted 127.0.0.1;\n";
+    if (xCAT::Utils->isServiceNode()) {
+      my $master=xCAT::Utils->get_site_Master();
+      push @$content, "  trusted $master;\n";
+    }
     push @$content,"}\n";
     #push @$content,"#xCAT END ACCESS\n";
   }
@@ -74,8 +206,16 @@ sub makeconservercf {
   }
   close $cfile;
   docfheaders(\@filecontent);
+
+  my $isSN=xCAT::Utils->isServiceNode();
+  my @hostinfo=xCAT::Utils->determinehostname();
+  my %iphash=();
+  foreach(@hostinfo) {$iphash{$_}=1;}
+
+  #print "process_request nodes=@$nodes\n";
+
   my $hmtab = xCAT::Table->new('nodehm');
-  my @cfgents = $hmtab->getAllNodeAttribs(['mgt','cons']);
+  my @cfgents = $hmtab->getAllNodeAttribs(['mgt','cons','conserver']);
 #cfgents should now have all the nodes, so we can fill in our hashes one at a time.
   foreach (@cfgents) {
     unless ($_->{cons}) {$_->{cons} = $_->{mgt};} #populate with fallback
@@ -89,6 +229,8 @@ sub makeconservercf {
     }
   }
   if (($nodes and @$nodes > 0) or $req->{noderange}->[0]) {
+    # strip all xCAT configured stuff from config if the original command was for all nodes
+    if ($req->{_allnodes}==1) {zapcfg(\@filecontent);}
     foreach (@$nodes) {
       my $node = $_;
       foreach (@cfgents) {
@@ -115,12 +257,19 @@ sub makeconservercf {
       }
     }
     foreach (@cfgents) {
-      if ($_->{termserver} and $termservers{$_->{termserver}}) {
-        dotsent($_,\@filecontent);
-        delete $termservers{$_->{termserver}}; #prevent needless cycles being burned
+      my $keepdoing=0;
+      if ($isSN && $_->{conserver} && exists($iphash{$_->{conserver}}))  { 
+        $keepdoing=1;  #only hanlde the nodes that use this SN as the conserver
       }
-      if ( $type{$_->{node}} !~ /fsp|bpa|hmc|ivm/ ) {
-        donodeent($_,\@filecontent);
+      if (!$isSN) { $keepdoing=1;} #handle all for MN
+      if ($keepdoing) {
+        if ($_->{termserver} and $termservers{$_->{termserver}}) {
+          dotsent($_,\@filecontent);
+          delete $termservers{$_->{termserver}}; #prevent needless cycles being burned
+        }
+        if ( $type{$_->{node}} !~ /fsp|bpa|hmc|ivm/ ) {
+          donodeent($_,\@filecontent);
+        }
       }
     }
   }
@@ -129,6 +278,12 @@ sub makeconservercf {
     print $cfile $_;
   }
   close $cfile;
+
+  #restart conserver daemon
+  my $cmd = "/etc/rc.d/init.d/conserver stop";
+  xCAT::Utils->runcmd($cmd, -1);
+  $cmd = "/etc/rc.d/init.d/conserver start";
+  xCAT::Utils->runcmd($cmd, -1);
 }
 
 sub dotsent {
@@ -139,6 +294,7 @@ sub dotsent {
   my $toidx = -1;
   my $skip = 0;
   my $skipnext = 0;
+
   while ($idx < $#$content) { # Go through and delete that which would match my entry
     if ($content->[$idx] =~ /^#xCAT BEGIN $tserv TS/) {
       $toidx=$idx; #TODO put it back right where I found it
@@ -160,7 +316,9 @@ sub dotsent {
   push @$content,"  host $tserv;\n";
   push @$content,"}\n";
   push @$content,"#xCAT END $tserv TS\n";
+  
 }
+
 sub donodeent {
   my $cfgent = shift;
   my $node = $cfgent->{node};
@@ -169,6 +327,9 @@ sub donodeent {
   my $toidx=-1;
   my $skip = 0;
   my $skipnext = 0;
+
+  my $isSN=xCAT::Utils->isServiceNode();
+
   while ($idx < $#$content) { # Go through and delete that which would match my entry
     if ($content->[$idx] =~ /^#xCAT BEGIN $node CONS/) {
       $toidx=$idx; #TODO put it back right where I found it
@@ -191,10 +352,17 @@ sub donodeent {
   #print $cmeth."\n";
   if (grep(/^$cmeth$/,@cservers)) { 
     push @$content," include ".$cfgent->{termserver}.";\n";
-    push @$content," port ".$cfgent->{termport}.";\n";
+    push @$content," port ".$cfgent->{termport}.";\n";   
+    if ((!$isSN) && ($cfgent->{conserver})) { # let the master handle it
+      push @$content,"  master ".$cfgent->{conserver}.";\n";
+    } 
   } else { #a script method...
     push @$content,"  type exec;\n";
-    push @$content,"  exec ".$::XCATROOT."/share/xcat/cons/".$cmeth." ".$node.";\n"
+    if ((!$isSN) && ($cfgent->{conserver})) { # let the master handle it
+      push @$content,"  master ".$cfgent->{conserver}.";\n";
+    } else { # handle it here
+      push @$content,"  exec ".$::XCATROOT."/share/xcat/cons/".$cmeth." ".$node.";\n"
+    }
   }
   push @$content,"}\n";
   push @$content,"#xCAT END $node CONS\n";
@@ -223,4 +391,49 @@ sub zapcfg {
   }
 }
 
+#--------------------------------------------------------------------------------
+=head3    enableConsOnSN
+      It configures the conserver on the service node if it is not configured yet.
+      It brings up the conserver daemon when xcatd starts.
+    Arguments:
+        none
+    Returns:
+        0 for successful.
+        non-0 for not successful.
+=cut
+#--------------------------------------------------------------------------------
+sub enableConsOnSN {
+  my $rc = 0;
+  if (xCAT::Utils->isServiceNode())  {
+    my @nodeinfo   = xCAT::Utils->determinehostname;
+    my $nodename   = pop @nodeinfo;                    # get hostname
+    my @nodeipaddr = @nodeinfo;                        # get ip addresses
+
+    my $service = "cons";
+    $rc = xCAT::Utils->isServiceReq($nodename, $service, \@nodeipaddr);
+    if ($rc == 1)   {
+      # service needed on this Service Node
+      $rc = &setup_CONS($nodename);                  # setup CONS
+      if ($rc == 0)  {
+         xCAT::Utils->update_xCATSN($service);
+      }
+    }
+    else  {
+      if ($rc == 2)  {    # already setup, just start the daemon
+        # start conserver
+        my $cmd = "/etc/rc.d/init.d/conserver start";
+        xCAT::Utils->runcmd($cmd, -1);
+      }
+    }
+  }
+}
+
 1;
+
+
+
+
+
+
+
+
diff --git a/xCAT-server-2.0/sbin/xcatd b/xCAT-server-2.0/sbin/xcatd
index 5967a7723..427396770 100755
--- a/xCAT-server-2.0/sbin/xcatd
+++ b/xCAT-server-2.0/sbin/xcatd
@@ -821,6 +821,7 @@ sub dispatch_request {
    #will for now be required for a command to be scaled through service nodes
    #If the plugin offers a preprocess method, use it to set the request array
    if (defined(${"xCAT_plugin::".$modname."::"}{preprocess_request})) {
+    undef $SIG{CHLD};
     $reqs = ${"xCAT_plugin::".$modname."::"}{preprocess_request}->($req,$dispatch_cb,\&do_request);
    } else { #otherwise, pass it in without hierarchy support
     $reqs = [$req];