#! /usr/perl5/bin/perl -w
#
# ident   "@(#)ShellScriptDumper.pm 1.1     03/11/27 SMI"
# 
# Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

# 
# Module: ScSnapshot::ShellScriptDumper
#
# Implementation of the abstract class ScSnapshot::InternalViewDumper
# used for creating shell scripts for a given view.
#

package ScSnapshot::ShellScriptDumper;
use strict;

# Inheritance declaration
@ScSnapshot::ShellScriptDumper::ISA = 
  qw(ScSnapshot::InternalViewDumper);

#
# Constructor.
#
sub new {
  my $proto = shift;
  my $class = ref($proto) || $proto;
  my $self = {};
  bless ($self, $class);
  return $self;
}

#
# Generates code for a given view into a given file handle.
# Arguments:
#   1) The view for which the code should be generated.
#      Cannot be undefined.
#   2) The file handle onto which the code should be generated.
#      Cannot be undefined.
#
sub dump {
  my $self = shift;
  my $view = shift;
  my $output = shift;
  my %buffers;
  
  # Print shell script header
  print $output "#!/bin/sh\n\n";
  print $output "#\n";
  print $output "# Generated by scsnapshot on ".localtime()."\n";
  print $output "#\n";
  
  print $output "\nSCRGADM=/usr/cluster/bin/scrgadm\n";
  
  # Generate code for user access checking
  print $output "\n# User access right checking: `resource.modify`\n";
  print $output "#----------------------------------------------\n";
  print $output "\necho \"[INFO] : Check credential for script running\"\n";
  print $output "AUTHS=`/usr/bin/auths`\n";
  print $output "if [      \\( -z \"`echo \$AUTHS | grep 'solaris\\.cluster\\.resource\\.modify'`\" \\) \\\n";
  print $output "       -a \\( -z \"`echo \$AUTHS | grep 'solaris\\.cluster\\.resource\\.\\*'`\" \\) \\\n";
  print $output "       -a \\( -z \"`echo \$AUTHS | grep 'solaris\\.cluster\\.\\*'`\" \\) \\\n";
  print $output "       -a \\( -z \"`echo \$AUTHS | grep 'solaris\\.\\*'`\" \\) ]; then\n";
  print $output "  echo \"`basename \$0` : Not authorized to run this command.\"\n";
  print $output "  echo \"Minimal access rights are 'solaris.cluster.resources.modify'.\"\n";
  print $output "  exit 3\n";
  print $output "fi\n";
  
  # Generate flag retrieval
  print $output "\nfflag=\n";
  print $output "while getopts f name\n";
  print $output "do\n";
  print $output "  case \$name in\n";
  print $output "    f) fflag=1;;\n";
  print $output "    ?) echo \"Usage Error:\"\n";
  print $output "       echo \"`basename \$0` [-f]\"\n";
  print $output "       exit 1;;\n";
  print $output "  esac\n";
  print $output "done\n";
  
  # Generate cmd wrapper function
  my $runcmd="run_cmd";
  print $output "\n# Command wrapper";
  print $output "\n#----------------\n";
  print $output "\n$runcmd() {\n";
  print $output "  cmd=\$1\n";
  print $output "  echo \"Running: \$cmd\"\n";
  print $output "  eval \$cmd\n";
  print $output "  ec=\$?\n";
  print $output "  if [ \$ec -ne 0 ]; then\n";
  print $output "    echo \"... ERROR: Exit status is: \$ec\"\n";
  print $output "    [ -z \"\$fflag\" ] && exit 1\n";
  print $output "  fi\n";
  print $output "}\n";  

  # Generate software version level checking
  foreach my $info (@{$view}) {
    if ($info->{Type} eq "METADATA") {
      my $scversion = $info->{Parameters}->{REQUESTED_SOFTWARE_VERSION};
      my $osversion = $info->{Parameters}->{REQUESTED_OS_VERSION};
      my $arch = $info->{Parameters}->{REQUESTED_ARCH};
      print $output "\n# Software version and architecture consistency check\n";
      print $output   "#----------------------------------------------------\n";
      print $output "\necho \"[INFO] : Check software version and architecture consistency\"\n";
      print $output "if [ -z \"\$fflag\" ]; then\n";
      print $output "  LOCAL_OS_VERSION=`/usr/bin/uname -r 2>/dev/null`\n";
      print $output "  LOCAL_ARCH=`/usr/bin/uname -p 2>/dev/null`\n";
      print $output "  LOCAL_SC_VERSION=`/usr/cluster/bin/scinstall -p 2>/dev/null | /usr/bin/head -1`\n";
      print $output "  if [ \"\$LOCAL_SC_VERSION\" != \"" 
	. $scversion . "\" -o \"\$LOCAL_OS_VERSION\" != \"" 
	. $osversion . "\" -o \"\$LOCAL_ARCH\" != \"" . $arch . "\" ]; then\n";
      print $output "    echo \"This script has been generated on a " . $arch .
	" cluster running Solaris $osversion and SunCluster version '$scversion'\"\n";
      print $output "    echo \"while the local cluster is running on \$LOCAL_ARCH machine Solaris \$LOCAL_OS_VERSION and " .
	"SunCluster version \$LOCAL_SC_VERSION.\"\n";
      print $output "    echo \"This message is to warn you that this " .
	"inconsistency might lead to errors.\"\n";
      print $output "    echo \"You can force the execution by running " .
	"the script with the -f force flag:\"\n";
      print $output "    echo \"\t`basename \$0` -f\"\n";
      print $output "    exit 1\n";
      print $output "  fi\n";
      print $output "else\n";
      print $output "  echo \"You're running this script using the force mode\"\n";
      print $output "fi\n\n";
    }
  }
    
  # Generate some code to check that all wished Resource Type are installed
  # on the machine.
  my @rtlist;
  foreach my $action (@{$view}) {
    if ($action->{Type} eq "CREATE_RESOURCE_TYPE") {
      @rtlist = (@rtlist, 
		 $action->{Parameters}->{RESOURCE_TYPE_NAME} . 
		 ":" . $action->{Parameters}->{RESOURCE_TYPE_VERSION} );
    }
  }

  if(@rtlist) {
    print $output "\n# Resource Type presence checking\n";
    print $output "#--------------------------------\n";
    print $output "\necho \"[INFO] : Resource Type presence checking:\"\n";
    print $output "RTLIST=\"" . join(" \\\n        ",@rtlist) . "\"\n";
    print $output "MISSING=\n";
    print $output "for each in \$RTLIST; do\n";
    print $output "  RTNAME=`echo \$each | /usr/bin/cut -f 1 -d \":\"`\n";
    print $output "  RTVERSION=`echo \$each | /usr/bin/cut -f 2 -d \":\"`\n";
    print $output "  if [ -z \"`\\grep RT_VERSION /usr/cluster/lib/rgm/rtreg/\$RTNAME* 2>/dev/null | \\grep \$RTVERSION 2>/dev/null`\" ]; then \n";
    print $output "    MISSING=\"\$MISSING \$each\"\n";
    print $output "  fi\n";
    print $output "done\n";
    print $output "if [ ! -z \"\$MISSING\" ]; then\n";
    print $output "  echo \"The Resource types listed above are not installed on this machine.\"\n";
    print $output "  echo \"Please install them before tyring to run this script again:\"\n";
    print $output "  echo \"\$MISSING\"\n";
    print $output "  exit 1\n";
    print $output "fi\n\n";
  }

  # Resource deletion handling
  my $preamble = "\n# Old resource definitions removal\n";
  $preamble .=     "# --------------------------------\n";
  $preamble .= "\necho \"[INFO] : Remove old Resources:\"\n";
  my $any = 0;
  my $code = "";

  foreach my $action (@{$view}) {
    if ($action->{Type} eq "DELETE_RESOURCE") {
      $any=1;
      my $name = $action->{Parameters}->{RESOURCE_NAME};
      $code .= "\n# $name\n";
      $code .= "$runcmd \"\$SCRGADM -r -j $name\"\n";
      $code.="\n# END\n";
    }
  }
  if ($any) {
    $preamble .= $code;
    print $output $preamble;
  }
  
  $preamble  = "\n# Old resource group definitions\n";
  $preamble .= "#-------------------------------\n";
  $preamble .= "\necho \"[INFO] : Remove old Resource Group definitions:\"\n";

  $code = "";
  $any = 0;

  # Resource group deletion handling
  foreach my $action (@{$view}) {
    if ($action->{Type} eq "DELETE_RESOURCE_GROUP") {
      $any = 1;
      my $name = $action->{Parameters}->{RESOURCE_GROUP_NAME};
      $code .= "\n# $name\n";
      $code .= "$runcmd \"\$SCRGADM -r -g $name\"\n";
      $code.="\n# END\n";
    }
  }
   
  if ($any) {
    $preamble .= $code;
    print $output $preamble;
  }
  
  $preamble  = "\n# Useless resource type definitions removal\n";
  $preamble .= "#------------------------------------------\n";
  $preamble .= "\necho \"[INFO] : Remove useless Resource Types:\"\n";

  $code = "";
  $any = 0;

  # Writing code for old resource type removal
  foreach my $action (@{$view}) {
    if ($action->{Type} eq "DELETE_RESOURCE_TYPE") {
      $any =1 ;
      my $name = $action->{Parameters}->{RESOURCE_TYPE_NAME};
      $code .= "\n# $name\n";
      $code .= "$runcmd \"\$SCRGADM -r -t $name\"\n";
      $code.="\n# END\n";
    }
  }
   
  if ($any) {
    $preamble .= $code;
    print $output $preamble;
  }	

  $preamble  = "\n# Resource Type definitions\n";
  $preamble .=   "#--------------------------\n";
  $preamble .= "\necho \"[INFO] : Register needed Resource Types:\"\n";
  $code = "";
  $any =0;

  # Write code relative to resource type creation
  foreach my $action (@{$view}) {
    if ($action->{Type} eq "CREATE_RESOURCE_TYPE") {
      $any=1;
      my $name = $action->{Parameters}->{RESOURCE_TYPE_NAME} . ":" 
	. $action->{Parameters}->{RESOURCE_TYPE_VERSION} ;
      $code .= "\n# $name\n";
      $code .= "$runcmd \"\$SCRGADM -a -t $name";
      if ((my $nodes = $action->{Parameters}->{INSTALLED_ON_NODES}) ne "*") {
	$code .= " -h $nodes";
      }
      $code.="\"\n\n# END\n";
    }
  }
   
  if ($any) {
    $preamble .= $code;
    print $output $preamble;
  }		

  $preamble =  "\n# Resource group definitions\n";
  $preamble .=   "#---------------------------\n";
  $preamble .= "\necho \"[INFO] : Add new Resource Group definitions:\"\n";

  $code = "";
  $any = 0;

  # Write code for resource group creations
  foreach my $action (@{$view}) {
    
    if ($action->{Type} eq "CREATE_RESOURCE_GROUP") {
      $any=1;
      my $name = $action->{Parameters}->{RESOURCE_GROUP_NAME};
      my $properties = $action->{Parameters}->{PROPERTIES};
      $code .= "\n# $name\n";
      my $nl=$properties->{nodelist};
      $code .= "$runcmd \"\$SCRGADM -a -g $name -h \\\"$nl\\\"";
      foreach my $property (keys(%{$properties})) {    
	if(lc($property) ne "nodelist") {
	  my $string = $properties->{$property};
	  $string =~ s/\"/\\\\\\\"/g;
	  $code .= " -y $property=\\\"$string\\\"";
	}
      }
      $code.="\"\n\n# END\n";
    }
  }
  
  if ($any) {
    $preamble .= $code;
    print $output $preamble;
  }	

  $preamble  = "\n# Resource definitions\n";
  $preamble .= "#---------------------\n";
  $preamble .= "\necho \"[INFO] : Add new Resource definitions:\"\n";
  $code = "";
  $any = 0;

  # Write code for resource creations :
  foreach my $action (@{$view}) {
    # General-purpose resource
    if ($action->{Type} eq "CREATE_RESOURCE") {
      $any=1;
      my $name = $action->{Parameters}->{RESOURCE_NAME};
      my $group = $action->{Parameters}->{RESOURCE_GROUP_NAME};
      my $type = $action->{Parameters}->{RESOURCE_TYPE_NAME};
      $code .= "\n# $name\n";
      $code .= "$runcmd \"\$SCRGADM -a -j $name -g $group -t $type";
      my $stdproperties = 
	$action->{Parameters}->{STANDARD_PROPERTIES};
      foreach my $property (keys(%{$stdproperties})) {
	my $string = $stdproperties->{$property};
	$string =~ s/\"/\\\\\\\"/g;
	$code .= " -y $property=\\\"$string\\\"";
      }
      my $extproperties = 
	$action->{Parameters}->{EXTENSION_PROPERTIES};
      foreach my $property (keys(%{$extproperties})) {
	my $string = $extproperties->{$property};
	$string =~ s/\"/\\\\\\\"/g;
	$code .= " -x $property=\\\"$string\\\"";
      }
      $code.="\"\n\n# END\n";
    }
    # LogicalHostname resource
    elsif ($action->{Type} eq "CREATE_LOGICAL_HOSTNAME_RESOURCE") {
      $any=1;
      my $name = $action->{Parameters}->{RESOURCE_NAME};
      my $group = $action->{Parameters}->{RESOURCE_GROUP_NAME};
      my $hostnamelist = $action->{Parameters}->{HOSTNAME_LIST};
      my $netiflist = $action->{Parameters}->{NETIF_LIST};
      $code .= "\n# ";
      $code .= (defined($name) && length($name))?$name:"anonymous";
      $code .= "\n";
      $code .= "$runcmd \"\$SCRGADM -a -L -g $group";
      if (defined($name) && length($name)) {
	$code .= " -j $name";
      }
      if(defined($hostnamelist) && length($hostnamelist)) {
	$code .=" -l $hostnamelist";
      }
      if (defined($netiflist) && length($netiflist)) {
	$code .= " -n $netiflist";
      }
      my $stdproperties = $action->{Parameters}->{STANDARD_PROPERTIES};
      foreach my $property (keys(%{$stdproperties})) {
	my $str = $stdproperties->{$property};
	$str =~ s/\"/\\\\\\\"/g;
	$code .= " -y $property=\\\"$str\\\"";
      }
      $code.="\"\n\n# END\n";
    }
    # SharedAddress resource
    elsif ($action->{Type} eq "CREATE_SHARED_ADDRESS_RESOURCE") {
      $any=1;
      my $name = $action->{Parameters}->{RESOURCE_NAME};
      my $group = $action->{Parameters}->{RESOURCE_GROUP_NAME};
      my $hostnamelist = $action->{Parameters}->{HOSTNAME_LIST};
      my $netiflist = $action->{Parameters}->{NETIF_LIST};
      my $auxnodelist = $action->{Parameters}->{AUXNODE_LIST};
      $code .= "\n# ";
      $code .= (defined($name) && length($name))?$name:"anonymous";
      $code .= "\n";
      $code .= "$runcmd \"\$SCRGADM -a -S -g $group";
      if (defined($name) && length($name)) {
	$code .= " -j $name";
      }
      if(defined($hostnamelist) && length($hostnamelist)) {
	$code .=" -l $hostnamelist";
      }
      if (defined($netiflist) && length($netiflist)) {
	$code .= " -n $netiflist";
      }
      if (defined($auxnodelist) && length($auxnodelist)) {
	$code .= " -X $auxnodelist";
      }
      my $stdproperties = 
	$action->{Parameters}->{STANDARD_PROPERTIES};
      foreach my $property (keys(%{$stdproperties})) {
	my $str = $stdproperties->{$property};
	$str =~ s/\"/\\\\\\\"/g;
	$code .= " -y $property=\\\"$str\\\"";
      }
      $code.="\"\n\n# END\n";
    }
  }

  if ($any) {
    $preamble .= $code;
    print $output $preamble;
  }		
} 

# Return success for module load
1; 
