You are on page 1of 80

#!/usr/bin/perl ############################################################################ # # # ems_install.pl - Just Install It! # # # # R.

Rozumalski - NOAA/NWS/FDTB/STRC # # # # January 2009 - Version 3 beta release # # # ############################################################################ # use strict; require 5.6.0; use vars qw (%EMSinstall); sub handler; $SIG{INT} = 'int_handle'; $ENV{VERBOSE} = 3; handler &user_opts; handler &ems_avail handler &ems_update if $EMSinstall{LIST}; if $EMSinstall{UPDATE};

handler &ems_release if $EMSinstall{RELEASE}; exit; sub handler { #--------------------------------------------------------------------------------# This routine handles the return values from the various ems_install routines . # Also determines whether to send email to specifies users in the event of a fa ilure. # # Simply return 0 if there was not a problem. #--------------------------------------------------------------------------------# my $ret = shift; my $mesg; return if $ret < 0; my $res = $ret > 0 ? 'Incomplete' : 'Complete'; if ($EMSinstall{LIST}) { my $res = 'Complete'; my $req = $EMSinstall{UPDATE} ? 'Update' : 'Release'; my $cmd = $ret ==-1 ? 'That\'s all I got to say on this matter' : $ret == 1 ? 'Now go forth and fix the problem!' : $ret == 2 ? 'Now go forth and Update!' : $ret == 3 ? 'Now go forth and Install the WRF EMS!' 'Now go forth and simulate!'; $mesg = sprintf("%s Listing %s - %s",$req,$res,$cmd); } else { my $req; my $cmd; if ($EMSinstall{INSTALL} eq '0') {

print "INSTALL: $req\n"; $req = $EMSinstall{UPDATE} ? 'Update Download' : $EMSinstall{RELEASE } ? 'Release Download' : 'Request'; $cmd = $ret > 0 ? 'Now go forth and fix the problem!' : 'Now go fort h and install!'; } else { $req = $EMSinstall{UPDATE} ? 'Update' : $EMSinstall{RELEASE} ? 'Inst allation' : 'Request'; $cmd = $ret > 0 ? 'Now go forth and fix the problem!' : 'Now go fort h and simulate!'; } $mesg = sprintf("Your %s is %s - %s",$req,$res,$cmd); } &emsprint(0,4,96,2,1,$mesg); $mesg = "Nigel Says - \"WRF EMS, It's taking mesoscale modeling to 11\""; &emsprint(0,4,96,1,3,$mesg); return; } #--------------------------------------------------------------------------------# sub user_opts { use Getopt::Long qw(:config pass_through); use Cwd; my %Option; # Begin by assigning the script name # @{$Option{RN}} = qw (I. II. III. IV. V. VI. VII. VIII. IX. X. XI. XII.); @{$Option{AB}} = qw (A. B. C. D. E. F. G. H. I. J. K. L. M. N. O. P. Q. R. S . T. U. W. X. Y. Z.); # Supported binaries # @{$Option{TBS}} = qw (x64 x32 p4 piv px penryn p7 k8 core2 athlonxp barcelon a); $ENV{VERBOSE} = 3; $Option{EXE} = &popit($0); $Option{PEXE} = cwd(); chomp $Option{PEXE}; $Option{PEXE} = "$Option{PEXE}/$Option{EXE}"; my $mesg; my $ver = '2010.03.04'; GetOptions ( "help|?" => sub {&help($Option{EXE})}, "emsdir=s" => \$Option{EMSDIR}, # The home partition for the distribution "updir=s" => \$Option{UPDIR}, # Override the default locat ion for the update files "reldir=s" => \$Option{RELDIR}, # Override the default locat

ion for the release files "locdir|repodir=s" => \$Option{REPODIR}, # Location or local repository for the update and release directories "dvd=s" => \$Option{DVD}, # Location of the DVD drive for DVD installation "update:s" => \$Option{UPDATE}, # Update to the requested re lease "install|release:s" => \$Option{RELEASE}, # Fresh install of t he requested release "revert:s" => \$Option{REVERT}, # revert back to a previous installation "nogeog" => \$Option{NOGEOG}, # Do not download and instal l the static geog data sets "localize!" => \$Option{LOCALIZE},# Do not localize the existi ng domain directories "force" => \$Option{FORCE}, # Force the installation of and update or release "nolocal" => \$Option{NOLOCAL}, # Get the files from the ser ver only "listall" /releases "list" eases > current "match:s" ownload files "nomatch:s" => \$Option{NOMATCH}, # List of strings to exclude from download "tp|target=s"=> \$Option{TP}, # Install the binaries for th e target processor requested "x64" => \$Option{X64}, # Install the unified 64-bit binaries "x32" => \$Option{X32}, # Install the 32-bit binaries "p4|piv" => \$Option{PIV}, # Install the 32-bit P4-compa tible binaries "px" => \$Option{PX}, # Install the generic x86 32bit binaries "binonly:s" => \$Option{BINONLY}, # Update to the specified bin aries for the release "binlist|tplist"=> \$Option{BINLIST}, # List the supported targ et binaries "version" d get out "nowkp" om exercises "domtrans:s" => \$Option{DOMTRANS},# ting EMS installation "local" => \$Option{LOCAL}, # n the local system "scour" => \$Option{SCOUR}, # on "noinstall" => \$Option{NOINSTALL},# ted files "wget" => \$Option{WGET}, # "curl" => \$Option{CURL}, # "host:s" => \$Option{UPDATEHOST}, Transfer domains from exis Use the available files o Scour existing installati Do not install the reques Use wget for http requests Use curl for http requests # The hostname of the serv => \$Option{NOWKP}, # Don't Download the classro => \$Option{VER}, # Get the version number an => \$Option{MATCH}, # List of strings to match d => \$Option{LIST}, # List available updates/rel => \$Option{LISTALL}, # List all available updates

er from which to get the EMS files "debug" => \$Option{DEBUG}) or die &help($Option{EXE}); Turn on Debugging &help($Option{EXE},@ARGV) if @ARGV;

if ($Option{VER}) { $mesg = "What you have here is WRF EMS installation routine version $ver "; &emsprint(0,4,96,1,2,$mesg); exit; } if ($Option{BINLIST}) { $mesg = "The currently supported target binaries are:\n\n". " @{$Option{TBS}}"; &emsprint(0,4,96,1,2,$mesg); exit; } $mesg = "Greetings clearly intelligent and devastatingly good-looking WRF EM S user!"; &emsprint(0,4,96,2,1,$mesg); $mesg = "Welcome to the SOO Science and Training Resource Center (SOO/STRC) Weather Research ". "and Forecasting (WRF) Environmental Modeling System (EMS) installat ion and update routine.\n\n". "Phew! That's more than a mouthful."; &emsprint(0,4,68,1,1,$mesg); $Option{LIST} = 1 if $Option{LISTALL}; # Turn OFF installation of anything if --list or --listall is passed # if ($Option{LIST}) { undef $Option{UPDATE}; undef $Option{RELEASE} } $Option{XBIN} = $Option{X64} ? 'x64' : $Option{X32} ? 'x32' : $Option{PIV} ? 'piv' : $Option{PX} ? 'px' : 0; $Option{XBITS} = $Option{X64} ? 'x64' : ($Option{X32} or $Option{PIV} or $Op tion{PX}) ? 'x32' : 0; if ($Option{DVD}) { $Option{WORKSHOP}=1; $Option{RELEASE} = 'current'; $Option{REPODIR} = $Option{DVD}; undef $Option{UPDATE}; } elsif (-e '.dvd') { # DVD installation $Option{WORKSHOP}=1; $Option{DVD} = cwd(); $Option{RELEASE} = 'current'; $Option{REPODIR} = $Option{DVD}; undef $Option{UPDATE}; }

# Make sure user is not confused # if (defined $Option{UPDATE} and defined $Option{RELEASE}) { $mesg = "You can only have just one, either \"--update\" or \"--release\ ""; &ems_inspire($mesg); return 1; } unless (defined $Option{UPDATE} or defined $Option{RELEASE} or defined $Opti on{LIST}) { $mesg = "So what do you want from me?\n\nPlease include either \"--updat e [release]\" ". "or \"--install [release]\" when running ems_install.pl. For ex ample:\n\n". " % ems_install.pl --install [release version]\n". "Or\n". " % ems_install.pl --update [release version]\n\n". "The release version ". "is optional as the default is the most current release.\n\nAlso , more hand-holding ". "is provided by passing the \"--help\", i.e.,\n\n % ems_install .pl --help "; &ems_inspire($mesg); return 1; } # Notify the user if a release version is passed with the binonly flag # if ($Option{BINONLY} and ($Option{RELEASE} or $Option{UPDATE})) { $mesg = "Note: The --binonly option will be used to replace the binaries in the currently installed release."; &emsprint(1,4,96,1,1,$mesg); undef $Option{UPDATE}; $Option{RELEASE} = 'current'; } if ($Option{BINONLY} and defined $Option{UPDATE}) { undef $Option{UPDATE}; $Option{RELEASE} = 'current'; } # Make sure the target binaries are supported # if (defined $Option{TP}) { unless ($Option{TP}) { $mesg = "You must include the target binary as an argument to the -target option.\n\n". "Current targets include:\n\n". " @{$Option{TBS}}"; &ems_inspire($mesg); return 1; } unless (grep /^$Option{TP}$/, @{$Option{TBS}}) { $mesg = "Requested target binary ($Option{BINONLY}) is not available . Available options are:\n\n". " @{$Option{TBS}}"; &ems_inspire($mesg);

return 1; } $Option{XBIN} = $Option{TP}; $Option{XBITS} = $Option{XBIN} =~ /64/ ? 'x64' : 'x32'; } if (defined $Option{BINONLY}) { unless ($Option{BINONLY}) { $mesg = "You must include the target binary as an argument to the -binonly option.\n\n". "Current targets include:\n\n". " @{$Option{TBS}}"; &ems_inspire($mesg); return 1; } unless (grep /^$Option{BINONLY}$/, @{$Option{TBS}}) { $mesg = "Requested target binary ($Option{BINONLY}) is not available . Available options are:\n\n". " @{$Option{TBS}}"; &ems_inspire($mesg); return 1; } $EMSinstall{NOGEOG} = 1; } if ((defined $Option{MATCH} and !$Option{MATCH}) or (defined $Option{NOMATCH } and !$Option{NOMATCH})) { $mesg = "The \"--match\" and \"--nomatch\" options require a list of cha racter strings separated ". "by a comma (,)."; $Option{MATCH} = 0; $Option{NOMATCH} = 0; &ems_inspire($mesg); } $Option{INSTALL} = 0 if $Option{NOINSTALL}; # bit confusing due to change. $Option{INSTALL} = 0 if $Option{MATCH} or $Option{NOMATCH}; if ($Option{NOWKP}) { $Option{NOMATCH} = $Option{NOMATCH} ? "workshop,$Option{NOMATCH}" : "wor kshop"; } # If either the --update or --release option was passed without an argument assume 'current' # $Option{UPDATE} = 'current' if defined $Option{UPDATE} and !$Option{UPDATE }; $Option{RELEASE} = 'current' if defined $Option{RELEASE} and !$Option{RELEAS E}; # Domains are included with an update. We only care about the new releases # undef $Option{DOMTRANS} unless $Option{RELEASE}; if ($Option{DOMTRANS}) { unless (-e $Option{DOMTRANS}) { $mesg = "You requested that existing computational domains from $Opt ion{DOMTRANS} ". "be transferred to the new installation; however, this direc tory does not appear ".

"to exist.\n\nAre you sure this is correct?"; &ems_inspire($mesg); return 1; } # Check if the use specified a directory with existing domains # my $valid = 0; opendir DIR => $Option{DOMTRANS}; foreach (readdir(DIR)) { next if $_ eq "." or $_ eq ".."; $valid = 1 if -e "$Option{DOMTRANS}/$_/static"; } closedir DIR; unless ($valid) { $mesg = "You have requested that existing computational domains from $Option{DOMTRANS} ". "be transferred to the new installation; however, this direc tory does not appear ". "to contain any valid domains. Are you sure this is correct ?"; &ems_inspire($mesg); return 1; } } # Make sure the EMSDIR option is correctly specified. # if ($Option{EMSDIR}) {$Option{EMSDIR} = "$Option{EMSDIR}/wrfems" if &popit($ Option{EMSDIR}) ne 'wrfems';} # If the user did not provide an argument to --domtrans # $Option{DOMTRANS} = 0 if defined $Option{DOMTRANS} and !$Option{DOMTRANS}; for my $opt (keys %Option) {$EMSinstall{$opt} = $Option{$opt} if defined $Op tion{$opt};} # Initialize the DYKs for the installation # @{$EMSinstall{DYKS}} = &dykinit; return -1; # value < 0 is good } sub ems_avail { #-----------------------------------------------------------------------------------------# This routine handles all requests for the updating of the WRF EMS #-----------------------------------------------------------------------------------------# my @updates; my @releases; my $mesg; # Get some valuable system information # ($EMSinstall{XBIN},$EMSinstall{XBITS},$EMSinstall{NCPUS},$EMSinstall{NCORES} ,$EMSinstall{INFO}) = &sysinfo; &emsprint(0,11,96,1,2,$EMSinstall{INFO}) unless ($EMSinstall{LIST} and !$EMS

install{LISTALL}); my $irel = &get_iver; $irel = 'No WRF EMS Installed' if $irel eq '00.00.00.0 0'; my $stat = ($irel eq 'No WRF EMS Installed') ? 3 : 2; return 1 if &get_avails; # Now create lists containing the sorted updates and releases. This is a bi t messy # as the file names must be reformateed for the Perl sort routines. # # @updates contains the correctly sorted list of available EMS updates # @releases contains the correctly sorted list of available EMS releases # @updates = &sort_release(keys %{$EMSinstall{UPDATES}}); @releases = &sort_release(keys %{$EMSinstall{RELEASES}}); # Print a summary of the releases and updates for the user # $mesg = "Here is a Summary of the Current WRF EMS Full Releases and Updates" ; &emsprint(1,4,96,1,1,$mesg); &emsprint(0,9,96,1,1,"Currently Installed Release : $irel"); my $n=0; my $beta; my $dev; my @frels=(); foreach (@releases) { next unless $_; next if /^wrfgeog|^wrf\.geog/i; if (/dev$/i) {$dev = $_; next;} if (/beta$/i) {$beta= $_; next;} push @frels => $_; } &emsprint(0,9,96,1,1,"Summary of Available WRF EMS Releases"); # Print out the available full releases # $mesg = @frels ? 'Available Full Releases:' : 'Available Full Releases: None '; &emsprint(0,11,96,1,0,"$mesg"); foreach (@frels) { $_ = sprintf ("%-12s",$_); $n++ ? $irel eq $_ ? &emsprint(0,36,96,1,0,"$_ -> Currently Installed") : &emsprint(0,36,96,1,0,"$_") : &emsprint(0,36,96,1,0,"$_ -> Most Current Official Release"); s/ //g; } &emsprint(0,36,96,1,0," ") if @frels; if ($beta) { my $str = ($irel eq $beta) ? "Available Beta Release : $beta -> Currentl y Installed" :

"Available Beta Release : $beta"; &emsprint(0,11,96,1,1,$str); } if ($dev) { my $str = ($irel eq $dev) ? "Available Dev Release : $dev -> Currently Installed" : "Available Dev Release : $dev"; &emsprint(0,11,96,1,1,$str); } if ($EMSinstall{LISTALL}) { foreach my $release (@releases) { my @relfiles = &subset(@{$EMSinstall{RELEASES}{$release}}); &emsprint(0,11,96,2,1,"Release $release files on server $EMSinstall{ UPDATEHOST}"); foreach my $file (@relfiles) { $file = &popit($file); next if $file =~ /wrf\.geog/; &emsprint(0,13,96,1,0,"File: $file"); } } &emsprint(0,14,96,1,0," "); } my $n=0; my $beta; my $dev; my @fupds=(); foreach (@updates) { next unless $_; if (/dev$/i) {$dev = $_; next;} if (/beta$/i) {$beta= $_; next;} push @fupds => $_; } &emsprint(0,9,96,2,1,"Summary of Available WRF EMS Updates"); # Print out the available full releases # $mesg = @fupds ? 'Available Full Updates :' : 'Available Full Updates : None '; &emsprint(0,11,96,1,0,"$mesg"); foreach (@fupds) { $_ = sprintf ("%-12s",$_); $n++ ? $irel eq $_ ? &emsprint(0,36,96,1,0,"$_ -> Installed Release") : &emsprint(0,36,96,1,0,"$_") : &emsprint(0,36,96,1,0,"$_ -> Most Current Update"); s/ //g; } &emsprint(0,36,96,1,0," ") if @fupds; if ($beta) { my $str = ($irel eq $beta) ? "Available Beta Update : $beta -> Currentl y Installed" : "Available Beta Update : $beta"; &emsprint(0,11,96,1,1,$str); }

if ($dev) { my $str = ($irel eq $dev) ? "Available Dev Update : $dev -> Currently Installed" : "Available Dev Update : $dev"; &emsprint(0,11,96,1,1,$str); } if ($EMSinstall{LISTALL}) { foreach my $update (@updates) { my @updatefiles = &subset(@{$EMSinstall{UPDATES}{$update}}); &emsprint(0,11,96,2,1,"Update $update files on server $EMSinstall{UP DATEHOST}"); foreach my $file (@updatefiles) { $file = &popit($file); next if $file =~ /wrf\.geog/; &emsprint(0,13,96,1,0,"File: $file"); } &emsprint(0,14,96,1,0," "); } } &emsprint(6,6,96,2,1,"No Need for an EMS Update at this Time - You are Curre nt") if $irel eq $releases[0]; return ($irel eq $releases[0]) ? 0 : $stat; } sub ems_update { #-----------------------------------------------------------------------------------------# This routine handles all requests for the updating of the WRF EMS #-----------------------------------------------------------------------------------------# my $mesg; my @updates; my @errs = qw (-1 0 1); # Make sure your system is configured correctly # return 1 if &prep_update; # Get the current release information my $irel = &get_iver; return 1 if &get_avails; &emsprint(0,9,78,2,1,"Current Installed Release: $irel") if $EMSinstall{DEBU G}; if ($irel eq '00.00.00.00') { $mesg = "I am unable to determine the version of the EMS release current ly installed ". "on your machine, which is a problem because I don't know what t o update.\n\n". "After a very brief consultation with the EMS elders it is recom mended ". "that you just harden up and do a fresh install."; &ems_inspire($mesg);

return 1; } # Now create a sorted list containing all the updates. This is a bit messy # as the file names must be reformateed for the Perl sort routines. # # @updates contains the correctly sorted list of available EMS updates # @updates = &sort_release(keys %{$EMSinstall{UPDATES}}); unless (@updates) { $mesg = "There appears to be a possible problem in that either there are ". "no updates available on the EMS server or that there was a prob lem ". "getting the list of updates.\n\n". "Either way, I am unable to continue with your request."; &ems_inspire($mesg); return 1; } if ($EMSinstall{DEBUG}) { &emsprint(0,9,78,1,2,"All Available Updates After Sorting"); &emsprint(1,11,78,0,1,"UPDATE: $_") foreach @updates; } # Reconcile the full list with what is needed # # Add the current release to the head of the list # This will be used for comparison with the other names # during other tasks. # unshift @updates => $irel; @updates = &reconcile(@updates); return $updates[0] if (grep $_ == $updates[0], @errs); # There are no file to process if ($EMSinstall{DEBUG}) { &emsprint(0,9,78,1,2,"After Reconciling of Updates"); &emsprint(1,11,78,0,1,"UPDATE: $_") foreach @updates; &emsprint(1,11,78,0,1,"UPDATE: None Needed") unless @updates; } # At this point we should have a list of files that must be downloaded # and installed for the update OR an error (1). The list and location # of the files is contained in the %EMSinstall{UPDATES} hash # # Note that the @updates list contains the REVERSE ORDERED list of # files to download. # $mesg = "Updates Need to Bring WRF EMS to Requested Level ($updates[0]):"; &emsprint(1,4,78,2,2,$mesg); &emsprint(0,9,78,0,1,"Update Release: $_") foreach reverse @updates; # Determine which files, if any need to be downloaded from server #

foreach my $update (reverse @updates) { # We need to to the download of all non-binary tar files. The binary ta r files # will be downloaded and installed after the system information is obta ined # # my my my with the cpuid routine, which is included in the distribution. @static =(); @binaries =(); @release =();

# The final resting place for the Release files # $EMSinstall{UPDIR} = "$EMSinstall{UPDIR}/$update"; return 1 if &mkdir($EMSinstall{UPDIR}); my @upfiles = &subset(@{$EMSinstall{UPDATES}{$update}}); # Organize the succession of tar files # foreach my $file (@upfiles) { if ($file =~ /wrf\.geog_/) { push @static => $file unless $EMSinstall{NOGEOG}; } elsif (grep $file =~ /\.$_\./, @{$EMSinstall{TBS}}) { push @binaries => $file; } elsif ($file =~ /update\./) { push @release => $file unless /\.penryn\.|\.p7\.|\.k8\.|\.core2\ .|\.athlonxp\./; } } &emsprint(1,4,78,2,2,"Checking for WRF EMS V$update update files"); my $nf = @release; my $n = 0; foreach my $rfile (sort @release) { my $lsfile = &popit($rfile); next unless $lsfile; my $lfile = "$EMSinstall{UPDIR}/$lsfile"; $n++; my $cnt = sprintf ("%10s","$n of $nf :"); $mesg = sprintf("$cnt EMS %-43s - ",$lsfile); &emsprint(0,9,108,0,0,$mesg); if (-e $lfile and !-z $lfile and !$EMSinstall{NOLOCAL}) { &emsprint(0,1,14,0,0,"Found Locally"); } else { # Go get the files # if ($EMSinstall{REPODIR}) { return 1 if system "cp -f $rfile $lfile"; &emsprint(0,1,12,0,0,"Copied"); } else { return 1 if &httpget($rfile,$lfile,$EMSinstall{UTIL}); &emsprint(0,1,12,0,0,"Downloaded"); } } if ($EMSinstall{INSTALL} eq '0') {

&emsprint(0,1,12,0,1," "); next; } return 1 if &unpack($lfile,$EMSinstall{EMSDIR}); &emsprint(0,1,12,0,1,"& Installed"); } # We need to determine which binary files to install but up until # this time the cpuid routine was not available. It is now. # (my $tbin, my $tcores) = &target; $EMSinstall{XBIN} = $tbin unless $EMSinstall{XBIN}; &emsprint(1,4,78,1,2,"Determining which $EMSinstall{XBIN} binary files t o obtain"); my @bins=(); foreach (@binaries) { next unless /\.$EMSinstall{XBIN}/; next unless $_; push @bins => $_; } @binaries = sort @bins; $nf = @binaries; $n = 0; unless (@binaries) { $mesg = "Problem? - No $EMSinstall{XBIN} binary files were found"; &emsprint(1,7,78,1,1,$mesg); } foreach my $rfile (sort @binaries) { my $lsfile = &popit($rfile); my $lfile = "$EMSinstall{UPDIR}/$lsfile"; $n++; my $cnt = sprintf ("%10s","$n of $nf :"); $mesg = sprintf("$cnt EMS %-44s - ",$lsfile); &emsprint(0,9,108,0,0,$mesg); if (-e $lfile and !-z $lfile and !$EMSinstall{NOLOCAL}) { &emsprint(0,1,14,0,0,"Found Locally"); } else { if ($EMSinstall{REPODIR}) { return 1 if system "cp -f $rfile $lfile"; &emsprint(0,1,12,0,0,"Copied"); } else { return 1 if &httpget($rfile,$lfile,$EMSinstall{UTIL}); &emsprint(0,1,12,0,0,"Downloaded"); } } if ($EMSinstall{INSTALL} eq '0') { &emsprint(0,1,12,0,1," "); next; } return 1 if &unpack($lfile,$EMSinstall{EMSDIR}); &emsprint(0,1,12,0,1,"& Installed"); }

return if $EMSinstall{INSTALL} eq '0'; # Now it is time to do the configuration of the EMS # return 1 if &configure_ems; } &domain_update; return; } # End of ems_update sub ems_release { #-----------------------------------------------------------------------------------------# This routine handles all requests for installing fresh WRF EMS releases #-----------------------------------------------------------------------------------------# my $mesg; my @releases; # Make sure your system is configured correctly # return 1 if &prep_install; # At this point we should have a wrfems directory on the system # Now we need to get the system information to determine which # release files to download. # # Get the current release information # my $irel = &get_iver("$EMSinstall{EMSDIR}"); my $frel = $irel; $frel = 'No WRF EMS Installed' if $frel eq '00.00.00.00'; &emsprint(0,9,78,2,1,"Current Installed Release: $frel") if $EMSinstall{DEBU G}; if ($EMSinstall{BINONLY}) { $EMSinstall{RELEASE} = $irel; if ($irel eq '00.00.00.00') { $mesg = "Unable to determine which binary release to install since y our ". "current installation appears to be version $irel."; &ems_inspire($mesg); return 1; } } return 1 if &get_avails; # Now create a sorted list containing all the updates. This is a bit messy # as the file names must be reformatted for the Perl sort routines. # # @releases contains the correctly sorted list of available EMS releases # @releases = &sort_release(keys %{$EMSinstall{RELEASES}});

unless (@releases) { $mesg = "There appears to be a possible problem in that either there are ". "no releases available on the EMS server or that there was a pro blem ". "getting the list of releases.\n\n". "Either way, I am unable to continue with your request."; &ems_inspire($mesg); return 1; } if ($EMSinstall{DEBUG}) { &emsprint(0,9,78,1,2,"All Available Releases on Server"); &emsprint(1,11,144,0,2,"RELEASE : $_\nLOCATION: $EMSinstall{RELEASES}{$_ }") foreach @releases; } # Reconcile the full list with what is needed # # It is assumed that the user knows what they are doing and that # the release requested is the one they want. Nonetheless, we must # check that the requested release exists and provide a warning # should they be reverting to an earlier release. # return $releases[0] unless @releases and $releases[0] != 1; # There are no file to process # Now handle argument passed to the --release option # $EMSinstall{RELEASE} = $releases[0] if $EMSinstall{RELEASE} eq 'current'; # Does the requested release actually exist? # if ($EMSinstall{BINONLY}) { unless (grep /^$EMSinstall{RELEASE}$/ => @releases) { $mesg = "Unavailable Release: $EMSinstall{RELEASE}\n\n". "It appears that you are attempting to install binaries for a release that is ". "no longer on the server. It may be time to update your EMS or do a fresh ". "installation of the current release."; &ems_inspire($mesg); return 1; } } else { unless (grep /^$EMSinstall{RELEASE}$/ => @releases) { my $ems = &popit($EMSinstall{EMSDIR}); &rm($EMSinstall{EMSDIR}) if $ems eq 'wrfems'; $mesg = "Fantasy Release: $EMSinstall{RELEASE}\n\n". "It appears that you are attempting to install a non-existen t release, ". "$EMSinstall{RELEASE}. You can use the \"--list\" option to list out ". "any updates or releases for which you are eligible."; &ems_inspire($mesg); return 1;

} if ($irel eq $EMSinstall{RELEASE} and !$EMSinstall{FORCE}) { $mesg = "Hey, the requested release, $irel, is the same as that alre ady installed ". "on the local system. If you are true about your intent then use the \"--force\" ". "option to tell me that you really, really mean care."; &ems_inspire($mesg); return 1; } } # # my my my ; if (&rel_frmt($rfv,$ifv) < 0 and !$EMSinstall{FORCE}) { # Release is earlie r $mesg = "Installation Faux Paux: $irel > $EMSinstall{UPDATE}\n\n". "Did you know that you are attempting to install earlier release . ". "than the one that currently resides on the system?\n\n". "If you are true about your intent then use the \"--force\" ". "option to tell me that you really, really mean care."; &ems_inspire($mesg); return 1; } $mesg = "I shall be Installing WRF EMS Version $EMSinstall{RELEASE}. Is this OK by you? [OK by me]: "; $mesg = "Installing the $EMSinstall{BINONLY} binaries for EMS Version $EMSin stall{RELEASE}. Is this OK by you? [OK by me]: " if $EMSinstall{BINONLY}; &emsprint(0,7,922,1,0,$mesg); my $ans = <>; chomp $ans; my $resp = $ans ? $ans : "Yes"; unless ($resp =~ /^Y/i) { $mesg = "Well, maybe we can try again later. - Bye"; &emsprint(0,9,92,1,1,$mesg); my $ems = &popit($EMSinstall{EMSDIR}); &rm($EMSinstall{EMSDIR}) if ($irel eq '00.00.00.00' and $ems eq 'wr fems' and !-e "$EMSinstall{EMSDIR}/strc" and !$EMSinstall{BINONLY}); return 3; } # At this point we should have the release to be installed. # # $mesg = "Reconciling WRF EMS $EMSinstall{RELEASE} release installation files "; &emsprint(1,4,78,1,1,$mesg); # We need to to the download of all non-binary tar files. The binary tar fi Attemptng to install an earlier release @cfv = split /\./ => $releases[0]; my $cfv = join ".", @cfv[0..4]; @ifv = split /\./ => $irel; my $ifv = join ".", @ifv[0..4]; @rfv = split /\./ => $EMSinstall{RELEASE}; my $rfv = join ".", @rfv[0..4]

les # # # my my my will be downloaded and installed after the system information is obtained with the cpuid routine, which is included in the distribution. @static =(); @binaries =(); @release =();

# The final resting place for the Release files # $EMSinstall{RELDIR} = "$EMSinstall{RELDIR}/$EMSinstall{RELEASE}"; return 1 if &mkdir($EMSinstall{RELDIR}); my @relfiles = &subset(@{$EMSinstall{RELEASES}{$EMSinstall{RELEASE}}}); # Organize the succession of tar files # foreach my $file (@relfiles) { if ($file =~ /wrf\.geog_/) { next if $EMSinstall{BINONLY}; push @static => $file unless $EMSinstall{NOGEOG}; } elsif (grep $file =~ /\.$_\./, @{$EMSinstall{TBS}}) { push @binaries => $file; } elsif ($file =~ /release\./) { next if $EMSinstall{BINONLY}; push @release => $file; } } # Just making sure # @static=() if $EMSinstall{BINONLY}; @release=() if $EMSinstall{BINONLY}; unless ($EMSinstall{BINONLY}) { unless ($EMSinstall{NOGEOG}) { &emsprint(1,4,78,1,1,"Checking for WRF static and land use data sets "); foreach my $rfile (@static) { my $lsfile = &popit($rfile); $mesg = sprintf("%-2s %-90s",shift @{$EMSinstall{AB}},&sdsets($l sfile)); &emsprint(0,9,168,1,1,$mesg); &didyouknow; my $lfile = "$EMSinstall{RELDIR}/$lsfile"; unless (-e $lfile and !-z $lfile and !$EMSinstall{NOLOCAL}) { # Go get the files # if ($EMSinstall{REPODIR}) { return 1 if system "cp -f $rfile $lfile"; } else { return 1 if &httpget($rfile,$lfile,$EMSinstall{UTIL}); } } if ($EMSinstall{INSTALL} eq '0') { &emsprint(0,1,12,0,1," ");

next; } return 1 if &unpack($lfile,$EMSinstall{EMSDIR}); &emsprint(0,12,94,1,2,"While you were waiting the $lsfile data s et was installed"); } } &emsprint(1,4,78,1,2,"Checking for WRF EMS release files") unless $EMSin stall{BINONLY}; my $nf = @release; my $n = 0; foreach my $rfile (@release) { my $lsfile = &popit($rfile); next unless $lsfile; my $lfile = "$EMSinstall{RELDIR}/$lsfile"; $n++; my $cnt = sprintf ("%10s","$n of $nf :"); $mesg = sprintf("$cnt EMS %-43s - ",$lsfile); &emsprint(0,9,108,0,0,$mesg); if (-e $lfile and !-z $lfile and !$EMSinstall{NOLOCAL}) { &emsprint(0,1,14,0,0,"Found Locally"); } else { # Go get the files # if ($EMSinstall{REPODIR}) { return 1 if system "cp -f $rfile $lfile"; &emsprint(0,1,12,0,0,"Copied"); } else { return 1 if &httpget($rfile,$lfile,$EMSinstall{UTIL}); &emsprint(0,1,12,0,0,"Downloaded"); } } if ($EMSinstall{INSTALL} eq '0') { &emsprint(0,1,12,0,1," "); next; } return 1 if &unpack($lfile,$EMSinstall{EMSDIR}); &emsprint(0,1,12,0,1,"& Installed"); } } # We need to determine which binary files to install but up until # this time the cpuid routine was not available. It is now. # $EMSinstall{XBIN} = $EMSinstall{BINONLY} if $EMSinstall{BINONLY}; (my $tbin, my $tcores) = &target; $EMSinstall{XBIN} = $tbin unless $EMSinstall{XBIN}; &getprocs unless $EMSinstall{BINONLY}; &emsprint(1,4,78,1,2,"Determining which $EMSinstall{XBIN} binary files to ob tain"); my @bins=();

foreach (@binaries) { next unless /\.$EMSinstall{XBIN}/; next unless $_; push @bins => $_; } @binaries = sort @bins; my $nf = @binaries; my $n = 0; unless (@binaries) { $mesg = "Problem? - No $EMSinstall{XBIN} binary files were found"; &emsprint(1,7,78,1,1,$mesg); } foreach my $rfile (@binaries) { my $lsfile = &popit($rfile); my $lfile = "$EMSinstall{RELDIR}/$lsfile"; $n++; my $cnt = sprintf ("%10s","$n of $nf :"); $mesg = sprintf("$cnt EMS %-44s - ",$lsfile); &emsprint(0,9,108,0,0,$mesg); if (-e $lfile and !-z $lfile and !$EMSinstall{NOLOCAL}) { &emsprint(0,1,14,0,0,"Found Locally"); } else { if ($EMSinstall{REPODIR}) { return 1 if system "cp -f $rfile $lfile"; &emsprint(0,1,12,0,0,"Copied"); } else { return 1 if &httpget($rfile,$lfile,$EMSinstall{UTIL}); &emsprint(0,1,12,0,0,"Downloaded"); } } if ($EMSinstall{INSTALL} eq '0') { &emsprint(0,1,12,0,1," "); next; } return 1 if &unpack($lfile,$EMSinstall{EMSDIR}); &emsprint(0,1,12,0,1,"& Installed"); } return if $EMSinstall{INSTALL} eq '0'; if ($EMSinstall{BINONLY}) { &rm("$ENV{EMS_BIN}/\.$_") foreach @{$EMSinstall{TBS}}; system "touch $ENV{EMS_BIN}/\.$EMSinstall{BINONLY}"; return; } # Now it is time to do the configuration of the EMS # return 1 if &configure_ems; return; } # End of ems_release

sub prep_update { #-----------------------------------------------------------------------------------------# This routine does the initial prep work for the update #-----------------------------------------------------------------------------------------# my $mesg; # Make sure that the EMS environment variable is correctly set # $EMSinstall{EMSDIR} = $EMSinstall{EMSDIR} ? $EMSinstall{EMSDIR} : $ENV{EMS}; unless ($EMSinstall{EMSDIR}) { $mesg = "The top level of the WRF EMS is not defined, so I am unable to complete ". "whatever task you are requesting. So either you need to make su re that ". "the EMS environment variable is set or you can pass the \"--ems dir <path>\" ". "option.\n\n". "Just providing the type of service that YOU deserve!"; &ems_inspire($mesg); return 1; } unless (-e $EMSinstall{EMSDIR}) { $mesg = "I am looking for the WRF EMS here:\n\n". " $EMSinstall{EMSDIR}\n\n". "But I don't see it. Which one of us needs glasses?\n\n". "Either you need to make sure that the EMS environment variable ". "is correctly set or you can pass the \"--emsdir <path>\" option .\n\n". "Just providing the type of service that YOU deserve!"; &ems_inspire($mesg); return 1; } # Read the contents of the ems_install.conf file, which should be located i n the # $EMS/conf/ems_install directory. # my $iconf = "$ENV{EMS}/conf/ems_install/ems_install.conf"; unless (-e $iconf) { $mesg = "You appear to be missing the ems_install configuration file, w hich is used ". "to define all my necessary default settings. Go track down th e following ". "file and try me again:\n\n". " $iconf";

&ems_inspire($mesg); return 1; }

# # # my my

We need to make sure user commend-line options override those parameters from the configuration file. %ohash = %EMSinstall; %chash = &read_conf($iconf);

for my $opt (keys %chash) {$EMSinstall{$opt} = $chash{$opt} if defined $chas h{$opt};} for my $opt (keys %ohash) {$EMSinstall{$opt} = $ohash{$opt} if defined $ohas h{$opt};} $EMSinstall{ICONF} = $iconf; # Set the default path to the necessary directories # $EMSinstall{UPDIR} = $EMSinstall{UPDIR} ? $EMSinstall{UPDIR} : "$EMSinsta ll{EMSDIR}/updates"; return 1 if &mkdir($EMSinstall{UPDIR}); ($EMSinstall{XBIN},$EMSinstall{XBITS},$EMSinstall{NCPUS},$EMSinstall{NCORES} ,$EMSinstall{INFO}) = &sysinfo; &emsprint(0,11,96,1,2,$EMSinstall{INFO}); return; } # End prep_update sub prep_install { #-----------------------------------------------------------------------------------------# This routine does the initial prep work for the installation #-----------------------------------------------------------------------------------------# my $mesg; # If user is requesting an binary only install then simply check for an exi sting EMS # installation and return # if ($EMSinstall{BINONLY}) { unless (defined $ENV{EMS} and -d $ENV{EMS}) { $mesg = "You do not appear to have an existing EMS installation, pos sibly because ". "the environment variables are not set or it really does not exist. Consequently, ". "the --binonly option is of no use to you right now."; &ems_inspire($mesg); return 1; } unless (-e "$ENV{EMS_STRC}/.release") { $mesg = "You do not appear to have a valid EMS installation, possibl y because your previous ". "installation attempt was incomplete. Regardless, you may ne ed to complete a fresh ". "installation before playing with the --binonly option."; &ems_inspire($mesg);

return 1; } # Assume all is well for now # $EMSinstall{EMSDIR} = $ENV{EMS}; $EMSinstall{RELDIR} = $EMSinstall{RELDIR} ? $EMSinstall{RELDIR} : "$EM Sinstall{EMSDIR}/releases"; return; } return 1 if &install_greeting; return 1 if &install_setup; return 1 if &install_user; unless ($EMSinstall{EMSDIR}) { $mesg = "The top level of the WRF EMS is not defined, so I am unable to complete ". "whatever task you are requesting. So either you need to make su re that ". "the EMS environment variable is set or you can pass the \"--ems dir <path>\" ". "option.\n\n". "Just providing the type of service that YOU deserve!"; &ems_inspire($mesg); return 1; } unless (-e $EMSinstall{EMSDIR}) { $mesg = "I am looking for the WRF EMS here:\n\n". " $EMSinstall{EMSDIR}\n\n". "But I don't see it. Which one of us needs glasses?\n\n". "Either you need to make sure that the EMS environment variable ". "is correctly set or you can pass the \"--emsdir <path>\" option .\n\n". "Just providing the type of service that YOU deserve!"; &ems_inspire($mesg); return 1; } # Set the default path to the necessary directories # $EMSinstall{RELDIR} = $EMSinstall{RELDIR} ? $EMSinstall{RELDIR} : "$EMSin stall{EMSDIR}/releases"; return 1 if &mkdir($EMSinstall{RELDIR}); ($EMSinstall{XBIN},$EMSinstall{XBITS},$EMSinstall{NCPUS},$EMSinstall{NCORES} ,$EMSinstall{INFO}) = &sysinfo; &emsprint(0,11,96,1,2,$EMSinstall{INFO}); return; } # End prep_install

sub install_greeting { #-----------------------------------------------------------------------------------------# This routine does the initial prep work for the update #-----------------------------------------------------------------------------------------# my $mesg; &emsprint(1,4,92,2,1,"Start with the Initial User Interrogation"); $mesg = "Before we begin this rather painless installation process I will ne ed to ask you a few ". "questions regarding the location and ownership of the distribution. "; &emsprint(0,7,96,1,1,$mesg); if ($>) { $mesg = "Since you are not installing as root, ownership will be initial ly given to $ENV{USER} ". "and you can change it later. Also, you must have write permissi on to the installation ". "directory, which will be specified by you."; &emsprint(0,7,96,1,2,$mesg); } else { $mesg = "Since you are installing the release as root, the process shoul d go smoothly. You will ". "be asked for a user name to assign the ownership of the files a nd a location for the ". "installation. If the user does not exist then an account will b e created.\n\n". "Note that running the EMS currently requires that users run tcs h or csh as their shell. ". "This requirement may change someday but it won't be by tomorrow unless you are doing all ". "the work."; &emsprint(0,7,96,1,1,$mesg); } $mesg = "Do you wish to continue? [Yes] "; &emsprint(0,9,96,1,0,$mesg); my $ans = <>; chomp $ans; chomp $ans; $ans = $ans ? $ans : "Yes"; unless ($ans =~ /^Y/i) { &emsprint(0,7,20,1,2,"I'm rather disappointed in you!"); return 1; } &emsprint(0,7,20,1,1,"So let us continue this forbidden EMS dance..."); return; } sub install_setup { #---------------------------------------------------------------------------------# This routine gets the information needed to install the WRF EMS

#---------------------------------------------------------------------------------# use Cwd; use POSIX; my $mesg; &emsprint(1,4,92,2,1,"Finding that Perfect Home for the WRF EMS"); # Get the necessary install directory information if it is missing # Once obtain then do some testing to make sure it is valid. # # At this point we shall assume that this is a fresh install # $EMSinstall{EMSDIR} =~ s/\/wrfems//g if $EMSinstall{EMSDIR}; my $validdir; while (! $validdir) { unless ($EMSinstall{EMSDIR}) { $mesg = "So, where would you like to install your WRF EMS? [/usr1] " ; &emsprint(0,9,96,1,0,$mesg); my $ans = <>; chomp $ans; $EMSinstall{EMSDIR} = $ans ? $ans : "/usr1"; } $validdir = 1; if (! -d $EMSinstall{EMSDIR}) { $mesg = "OOPS! $EMSinstall{EMSDIR} is not a valid directory. Let us try it again."; &emsprint(0,7,96,1,1,$mesg); $validdir = 0; delete $EMSinstall{EMSDIR}; } elsif (! -w $EMSinstall{EMSDIR}) { $mesg = "BUMMER! $ENV{USER} does not have write permission on $EMSin stall{EMSDIR}."; &emsprint(0,7,96,1,1,$mesg); $mesg = "Do you want to continue? [No] "; &emsprint(0,9,96,1,0,$mesg); my $ans = <>; exit unless $ans =~ /^Y/i; $validdir = 0; delete $EMSinstall{EMSDIR}; } elsif ( -e "$EMSinstall{EMSDIR}/wrfems" ) { $validdir = 0; my $irel = &get_iver("$EMSinstall{EMSDIR}/wrfems"); my $idir = "wrfems.$irel"; my $ipth = "$EMSinstall{EMSDIR}/$idir"; if ($irel eq '00.00.00.00' and !-e "$EMSinstall{EMSDIR}/wrfems/strc" ) { # Must be a previously aborted attempt # &rm("$EMSinstall{EMSDIR}/wrfems"); $validdir = 1; } else { $mesg = "It appears that a WRF EMS installation already exists o

n $EMSinstall{EMSDIR}/wrfems.\n\n"; $mesg = "It appears that a WRF EMS installation already exists o n $EMSinstall{EMSDIR}/wrfems, ". "although I can not determine the release version, if an y. These files may be left over ". "from a previous failed/aborted installation attempt.\n\ n" if $irel eq '00.00.00.00'; &emsprint(6,7,92,2,0,$mesg); if (-e $ipth) { $mesg = "Should you decide to continue with this process, th e previous installation will ". "be renamed $ipth and the existing $idir will be del eted. You can decide what to ". "do with $ipth later."; } else { $mesg = "Should you decide to continue with this process, th e previous installation ". "will be renamed $ipth. You can decide whether to de lete the files later."; } &emsprint(0,10,92,1,0,$mesg); $mesg = "Do you wish to continue with $EMSinstall{EMSDIR}? [No] "; &emsprint(0,9,96,2,0,$mesg); my $ans = <>; $validdir = $ans =~ /^Y/i; if (-e # # # if $ipth and $validdir) { Make sure the user did not request computational domains from this installation.

("$ipth/runs" eq "$EMSinstall{DOMTRANS}") { $mesg = "Hmmm, I believe there is a problem in that you requested domains be transferred ". "from $EMSinstall{DOMTRANS}, which is about to b e deleted by this action. I'll ". "let you go with warning this time but it's in y our interest to simply rename ". "$ipth to something else and then try the instal lation one more time."; &ems_inspire($mesg); return 1; } $mesg = "Deleting previous $ipth"; &emsprint(6,7,92,1,1,$mesg); &rm($ipth); } system "mv $EMSinstall{EMSDIR}/wrfems $ipth" if $validdir; $EMSinstall{PREVREL} = $irel; if (defined $EMSinstall{DOMTRANS}) { $EMSinstall{DOMTRANS} = "$ipth/runs" if $EMSinstall{DOMTRANS } == 0; $EMSinstall{DOMTRANS} = "$ipth/runs" if $EMSinstall{DOMTRANS } eq "$EMSinstall{EMSDIR}/wrfems/runs"; }

delete $EMSinstall{EMSDIR} unless $validdir; } } } # Delete any existing WRF EMS directory and create a new one. # $EMSinstall{EMSDIR} = "$EMSinstall{EMSDIR}/wrfems"; &rm($EMSinstall{EMSDIR}); return 1 if &mkdir($EMSinstall{EMSDIR}); $mesg = "The WRF EMS distribution will be located in $EMSinstall{EMSDIR}"; &emsprint(0,7,92,1,1,$mesg); # Check if T|Cshell is installed # &emsprint(1,4,92,2,1,"Checking if T|Cshell is installed on the system"); $mesg = "IMPORTANT: The user assigned ownership of the WRF EMS must be runni ng ". "either a T or C shell environment. These shells must also be insta lled ". "on all systems running the EMS."; &emsprint(6,7,92,1,1,$mesg); my $shell = (-e "/bin/tcsh" or -e "/bin/csh"); &emsprint(1,10,22,1,0,"Is T shell installed? - "); -e "/bin/tcsh" ? &emsprint(0,1,20,0,0,"Yes") : &emsprint(0,1,20,0,0,"No"); &emsprint(1,10,22,1,0,"Is C shell installed? - "); -e "/bin/csh" ? &emsprint(0,1,20,0,1,"Yes") : &emsprint(0,1,20,0,1,"No"); unless ($shell) { $mesg = "It appears that neither /bin/csh nor /bin/tcsh is installed on your ". "system. The WRF EMS requires that one of these shells be instal led ". "and that it be assigned to the user running the system."; &emsprint(6,7,92,1,1,$mesg); my $ans = "Yes"; $mesg = "Do you wish to continue with the installation? [Yes] "; &emsprint(0,10,96,1,0,$mesg); my $ans = <>; chomp $ans; $ans = "Yes" unless $ans; unless ($ans =~ /^Y/i) { &rm($EMSinstall{EMSDIR}); exit; } } return $validdir ? 0 : 1; } sub install_user { #----------------------------------------------------------------------------------

# This routine checks to make sure you can use http to access the necessary # information on the outside server. #---------------------------------------------------------------------------------# my $mesg; &emsprint(1,4,92,1,1,"Enough About Me. What About ... YOU?"); $EMSinstall{USER} = ($ENV{USER} eq 'root') ? 'emsuser' : $ENV{USER}; if ($>) { $mesg = "The WRF EMS will be owned by user \"$ENV{USER}\". Good for you $ENV{USER}!"; &emsprint(0,7,92,1,1,$mesg); } else { my $noname=1; while ($noname) { $mesg = "To whom shall I assign guardianship of the EMS? [$EMSinstal l{USER}] "; &emsprint(0,9,92,1,0,$mesg); my $ans = <>; chomp $ans; $ans = $EMSinstall{USER} if !$ans and $EMSinstall{USER}; if (!$ans or $ans =~ /^root$/i) { $mesg = "Sorry but user $ans is not allowed. Try something witho ut \"root\" ". "in the name."; &emsprint(0,9,92,2,0,$mesg); } else { $EMSinstall{USER} = $ans ? $ans : $EMSinstall{USER}; $noname=0 if $EMSinstall{USER} ne 'root'; } } } my @user; if (@user = getpwnam $EMSinstall{USER}) { unless ($user[-1] =~ /\/bin\/tcsh|\/bin\/csh/) { my $s = &popit($user[-1]); $mesg = "WARNING: User $EMSinstall{USER} is NOT running a t|csh shel l! (current: $s)!\n\nBe sure ". "to fix this problem before running the EMS; otherwise, you will be greatly disappointed. ". "And we do not want that to happen now do we?"; &emsprint(6,7,92,1,1,$mesg); &emsprint(0,10,92,1,0,"I accept the consequences of not using the pr oper shell environment [Yes] "); my $ans = <>; chomp $ans; &emsprint(0,10,92,1,0," "); } } else { if (! $>) { $mesg = "User $EMSinstall{USER} does not exist on the system."; &emsprint(6,9,92,1,1,$mesg); $mesg = "Don't worry, I can create a user account for $EMSinstall{US ER}. System defaults will be used for the ". "user and group IDs, and login shell will be /bin/tcsh."; &emsprint(0,7,92,1,1,$mesg);

$mesg = "Do you want to create an account? [Yes] "; &emsprint(0,9,92,1,0,$mesg); my $ans = <>; chomp $ans; my $resp = $ans ? $ans : "Yes"; unless ($resp =~ /^Y/i) { $mesg = "You will have to create a user account for $EMSinstall{ USER} continuing. - Bye Bye"; &emsprint(0,7,92,2,2,$mesg); &rm($EMSinstall{EMSDIR}); return 1; } # check to see if /bin/tcsh is available on the system # unless (-e '/bin/tcsh' or -e '/sbin/tcsh' or -e '/usr/bin/tcsh') { $mesg = "Missing required tcsh shell on your system! Please inst all it run $EMSinstall{EXE} again."; &emsprint(6,7,92,2,2,$mesg); &rm($EMSinstall{EMSDIR}); return 1; } $mesg = "Please specify a password for user $EMSinstall{USER} [disab le account] "; &emsprint(0,9,92,1,0,$mesg); my $ans = <>; chomp $ans; my $pw = $ans ? $ans : ""; my $homedir = "-d /home/$EMSinstall{USER}"; my $desc = "-c \"STRC WRF EMS Owner\""; my $shell = "-s /bin/tcsh"; if (system "/usr/sbin/useradd -m $homedir $desc $shell $EMSinstall{U SER} >& /dev/null") { $mesg = "Creation of account for user $EMSinstall{USER} failed. Installing as user root"; &emsprint(3,7,92,1,1,$mesg); $mesg = "You will have to create the account for user $EMSinstal l{USER} manually and then change ownership"; &emsprint(0,7,92,1,1,$mesg); $mesg = "Is this OK with you? [Ok by me!] "; &emsprint(0,9,92,1,0,$mesg); my $ans = <>; chomp $ans; my $resp = $ans ? $ans : "Yes"; return 1 if $resp !~ /^Y|^O/i; } else { $EMSinstall{CSHRC} = 1; if ($pw) { &emsprint(0,7,92.1,0,"User account $EMSinstall{USER} created "); if (system "echo $pw | /usr/bin/passwd --stdin $EMSinstall{U SER} >& /dev/null") { &emsprint(6,7,92,1,2,"Password creation failed. Account i s currently disabled"); } else { &emsprint(0,7,92,1,2,"Password file updated"); }

} else { &emsprint(0,7,92,1,1,"User account $EMSinstall{USER} created "); $mesg = "Account initially disabled. You will have to run th e passwd command ". "to enable the account."; &emsprint(0,7,92,1,1,$mesg); } } } } return; } sub configure_ems { #--------------------------------------------------------------------------------# This routine does the post install/update configuration of the package #--------------------------------------------------------------------------------# my $mesg; $mesg = sprintf("Doing WRF EMS post-%s configuration",$EMSinstall{UPDATE} ? 'update' : 'install'); &emsprint(1,4,92,2,1,$mesg); unless ($EMSinstall{BINONLY}) { &file_update; # Create the runs directory # my $rdir = "$EMSinstall{EMSDIR}/runs"; &mkdir($rdir); # Run the post_install|update.pl routine. This routine does all the # release-specific configuration and clean up # my $postexe = $EMSinstall{UPDATE} ? 'post_update.pl' : 'post_install.pl' ; $postexe = "$EMSinstall{EMSDIR}/strc/ems_bin/$postexe"; he routine system ("$postexe $EMSinstall{EMSDIR}") if -e $postexe; &rm($postexe); # set the permissions and ownership of all the EMS files to the user # my @user = getpwnam $EMSinstall{USER}; $EMSinstall{GROUP} = getgrgid $user[3]; unless ($<) { &emsprint(0,10,92,1,1,"Setting ownership of WRF EMS distribution to $EMSinstall{USER}\:$EMSinstall{GROUP}"); system "/bin/chown -R $EMSinstall{USER}:$EMSinstall{GROUP} $EMSinsta ll{EMSDIR} >& /dev/null"; } &config_release if $EMSinstall{RELEASE}; # path to t

&config_update if $EMSinstall{UPDATE}; } # Need to copy the few archetecture-specific routines # system "cp $EMSinstall{EMSDIR}/util/bin/wgrib2.$EMSinstall{XBITS} $EMSinstal l{EMSDIR}/util/bin/wgrib2"; system "cp $EMSinstall{EMSDIR}/util/bin/wgrib.$EMSinstall{XBITS} $EMSinstal l{EMSDIR}/util/bin/wgrib"; my @bins = qw (.x32 .x64 .px .piv); &rm("$EMSinstall{EMSDIR}/bin/$_") foreach @bins; system("touch $EMSinstall{EMSDIR}/bin/.$EMSinstall{XBIN}"); # Create a backup of the benchmark files # # my @cores = qw(arw nmm); # foreach (@cores) { # system "cp -fr $EMSinstall{EMSDIR}/util/benchmark/$_/conf $EMSinstall{ EMSDIR}/data/benchmark/$_"; # system "cp -fr $EMSinstall{EMSDIR}/util/benchmark/$_/static $EMSinstall{ EMSDIR}/data/benchmark/$_"; # } # Finally copy the install routine into the strc directory # system("cp -f $EMSinstall{PEXE} $EMSinstall{EMSDIR}/strc/ems_bin"); &checklibs; return; } sub config_update { #------------------------------------------------------------------------------# Do some final cleanup of the WRF EMS following the update #------------------------------------------------------------------------------# &emsprint(1,9,92,1,1,"Cleaning up release"); # Clean up the previous release of all the no longer needed files # my $cflist = "$EMSinstall{EMSDIR}/logs/elimination_files.txt"; if (-e $cflist) { open CF => $cflist; my @cfiles = <CF>; close CF; foreach (@cfiles) { chomp; s/ +//g; next unless $_; &rm("$EMSinstall{EMSDIR}/$_") if -e "$EMSinstall{EMSDIR}/$_"; } } return; } sub config_release { #------------------------------------------------------------------------------# If this is a fresh install then place the included .cshrc file in the users # home directory. If an update then assume all is well but check anyway

#------------------------------------------------------------------------------# my $mesg; my @user = getpwnam $EMSinstall{USER}; my $uh = $user[-2]; if (-e $uh) { my $sf = "$uh/.cshrc"; open FILE, "$EMSinstall{EMSDIR}/.cshrc"; my @lines = <FILE>; close FILE; if (! -e $sf) { if (open FILE, ">$sf") { foreach (@lines) { chomp; s/EMSDIR/$EMSinstall{EMSDIR}/g; s/EMSRUN/"$EMSinstall{EMSDIR}\/runs"/g; print FILE "$_\n"; } close FILE; system "/bin/chown -R $EMSinstall{USER}:$EMSinstall{GROUP} $sf > & /dev/null"; } else { $mesg = "THIS IS IMPORTANT, WHICH IS WHY I AM YELLING\n\n". "You will have to manually add the following line to $EM Sinstall{USER}\'s ". "$sf file:\n\n". " if (-f $EMSinstall{EMSDIR}/EMS.cshrc) source $EMSinst all{EMSDIR}/EMS.cshrc"; &emsprint(6,7,92,1,1,$mesg); } } else { $mesg = "THIS IS IMPORTANT, WHICH IS WHY I AM YELLING\n\n". "Please make sure the following line is present in $EMSinsta ll{USER}\'s ". "$sf file:\n\n". " if (-f $EMSinstall{EMSDIR}/EMS.cshrc) source $EMSinstall{ EMSDIR}/EMS.cshrc"; &emsprint(6,7,92,1,1,$mesg); } } else { # If the user's home account does not exist $mesg = "It appears that the home directory for user $EMSinstall{USER} ( $uh) was never created. ". "So, in order to complete the EMS installation you will have to do the following:\n\n". " 1. Create a home account for $EMSinstall{USER} and make it a nice one with C shell!\n". " 2. Copy the $EMSinstall{EMSDIR}/.cshrc file to $uh\n". " 3. Make sure the following line is in the file:\n\n". " if (-f $EMSinstall{EMSDIR}/EMS.cshrc) source $EMSinstall {EMSDIR}/EMS.cshrc\n\n". " 4. Change the ownership of the file to user $EMSinstall{USER} \n". " 5. Make sure you change the ownership of the EMS distribution to user $EMSinstall{USER}\n"; &emsprint(6,7,92,1,1,$mesg); }

# If the user requested that domains be transferred. The configuration dire ctories # get updated later. # if ($EMSinstall{DOMTRANS}) { opendir DIR => $EMSinstall{DOMTRANS}; foreach (readdir(DIR)) { next if $_ eq "." or $_ eq ".."; if (-e "$EMSinstall{DOMTRANS}/$_/static") { &mkdir("$EMSinstall{EMSDIR}/runs/$_"); $mesg = "Copying existing EMS domain directory $_ to new release "; &emsprint(0,9,92,1,0,$mesg); system "cp -fr $EMSinstall{DOMTRANS}/$_/static $EMSinstall{EMSDI R}/runs/$_"; system "cp -fr $EMSinstall{DOMTRANS}/$_/conf $EMSinstall{EMSDI R}/runs/$_"; } } closedir DIR; &emsprint(0,9,92,1,0," "); &domain_update; } # Create/Modify the user's crontab file # my $ctfile = "$EMSinstall{EMSDIR}/logs/crontab.txt"; my @crontab=(); if ($<) { system "/usr/bin/crontab -l > $ctfile"; } else { if (system "/usr/bin/crontab -l -u $EMSinstall{USER} >& /dev/null") { system "/bin/touch $ctfile"; } else { system "/usr/bin/crontab -l -u $EMSinstall{USER} > $ctfile"; } } open TAB,"$ctfile"; my @lines = <TAB>; close TAB; foreach (@lines) { chomp; next if /ems_update|ems_autorun|ems_install/; next unless $_; push @crontab => $_; } # Add the ems_autorun and ems_install.pl entries. # # # # my my my Use random number generator to provide placeholders for hour and minute since I don't want users hitting the servar at the same time. $hr = int (rand 24); $mn = int (rand 60); $dy = int (rand 7 );

push @crontab => "#$mn $hr * * * $EMSinstall{EMSDIR}/strc/ems_bin/ems_instal l.pl --update current >> $EMSinstall{EMSDIR}/logs/ems_install.log 2>&1"; push @crontab => "#$mn $hr * * * $EMSinstall{EMSDIR}/strc/ems_bin/ems_autoru

n-wrapper.csh --rundir $EMSinstall{EMSDIR}/runs/<your domain> >& $EMSinstall{EMS DIR}/logs/ems_autorun.log 2>&1"; open TAB,">$ctfile"; print TAB "$_\n" foreach @crontab; $< ? system "/usr/bin/crontab $ctfile" : system "/usr/bin/crontab -u $EMSins tall{USER} $ctfile"; &rm($ctfile); return; } sub file_update { #-----------------------------------------------------------------------------------# Update the various configuration files and run-time scripts with the users # EMS path. The files to be configured are contained in the configuration_files .txt # located in the wrfems/logs directory. This file should be included with each # release and update. #-----------------------------------------------------------------------------------# my $mesg; my $cflist = "$EMSinstall{EMSDIR}/logs/configuration_files.txt"; return unless -e $cflist; # We need the notal number of processor on the system # my $nprocs = $EMSinstall{NCPUS} * $EMSinstall{NCORES}; open CF => $cflist; my @cfiles = <CF>; close CF; foreach my $file (@cfiles) { chomp $file; $file =~ s/ //g; next unless $file; $file = "$EMSinstall{EMSDIR}/$file"; unless (-e $file) { $mesg = "Not Configured: $file"; &emsprint(6,7,92,1,1,$mesg); next; } open CF => $file; my @flines = <CF>; close CF; # Read the contents of th e file open CF => ">$file"; # Open the file for writing foreach (@flines) { s/WRFEMS/$EMSinstall{EMSDIR}/g; s/EMSDIR/$EMSinstall{EMSDIR}/g; s/SYSCPUS/$EMSinstall{NCPUS}/g; s/SYSCORES/$EMSinstall{NCORES}/g; s/NPROCS/$nprocs/g; print CF $_; } close CF; } &rm($cflist); return;

} sub domain_update { #--------------------------------------------------------------------------------# This routine updates the various domain directories #--------------------------------------------------------------------------------# my $mesg; my @usedefault = qw (run_auxhist1.conf run_auxhist2.conf run_dynamics.conf r un_restart.conf run_vinterp.conf run_dfi.conf); my $runs = "$EMSinstall{EMSDIR}/runs"; my $ro; opendir DIR => $runs; foreach my $dom (readdir(DIR)) { next if $dom eq "." or $dom eq ".."; my $uc = uc $dom; &emsprint(0,9,92,2,1,"Updating configuration files in $uc as necessary") ; # $mesg = "IMPORTANT: of the user\n". # " s is that some\n". # " ange and it can\n". # " to change.\n\n". It is not currently possible to to a complete update configuration files at this time. The reason for thi of the default settings in the update/release may ch not be determined what parameters the user intended

# " Thus, you will have to manually edit the domain conf iguration files\n". # " for now."; # &emsprint(6,9,92,1,2,$mesg) unless $ro; $ro = 1; my $dd = $dom; my $dom = "$runs/$dom"; if (-e "$dom/static") { my $ucfgd = "$dom/conf"; ory my $dcfgd = "$EMSinstall{EMSDIR}/conf"; # Default config file direct ory my $nmm ctory? # If this is an update then move the existing configuration files # to the update directory along with the static directory # # It is not currently possible to to a complete update of the # user configuration files at this time. The reason for this is # that some of the default settings in the update/release may = (-e "$dom/static/.nmm") ? 1 : 0; # Is this an NMM dire # User config file direct

# # # # # # my ded

have changed and it can not be be determined which parameters the user intended to change. One could do a comparison between the current and previous default settings but that will be left to another release. @cdirs = qw (ems_auto ems_post ems_run); # That's all that is nee

foreach my $cdir (@cdirs) { # Open each file in the default conf dir, one at a time # opendir DCFGD => "$dcfgd/$cdir"; foreach my $dcfgf (readdir(DCFGD)) { next if $dcfgf eq "." or $dcfgf eq ".."; next unless $dcfgf =~ /\.conf$|.conf\.nmm$/; # Handle different physics config files # next if $dcfgf =~ /\.nmm/ and ! $nmm; next if $dcfgf eq 'run_physics.conf' and $nmm; (my $ucfgf = $dcfgf) =~ s/\.nmm//g; $dcfgf = "$dcfgd/$cdir/$dcfgf"; $ucfgf = "$ucfgd/$cdir/$ucfgf"; # If the configuration file does not exist in the user dir then # just copy it over and move on to the next file # my $f = &popit($ucfgf); if (-e $ucfgf) { if (grep /^$f$/, @usedefault) { &emsprint(0,12,114,1,0,"Using default configuration file - $f"); system "cp -f $dcfgf $ucfgf"; } else { &emsprint(0,12,114,1,0,"Updating with user configura tion - $f"); open DFILE => "$dcfgf";my @dlines = <DFILE>;close DF ILE; if ($f eq 'post_export.conf') { my @list = &read_conf($ucfgf); open CFILE, ">$ucfgf"; # Open for writing foreach (@dlines) { chomp; s/^\s+//g; print CFILE "$_\n" if /^#|^$|^\s+/; } foreach (@list) { chomp; s/^\s+//g; print CFILE "EXPORT = $_\n"; } } else { my %hash = &read_conf($ucfgf); open CFILE, ">$ucfgf"; # Open for writing

foreach (@dlines) { chomp; s/^\s+//g; if (/^#|^$|^\s+/) { print CFILE "$_\n"; next; } s/\t//g;s/\n//g; s/ //g unless /MPIRUNARGS/; if (/\s*=\s*/) { my ($var, $value) = split(/\s*=\s*/, $_, 2); $value = $hash{uc $var} if defined $hash {uc $var}; $var = uc $var; print CFILE "$var = $value\n"; } } } close CFILE; } next; } else { &emsprint(6,12,114,1,1,"Installing new configuration fil e - $dd/conf/$cdir/$f"); } } # foreach my $dcfgf } # Now re localize the domain # &localize($dom) unless $EMSinstall{LOCALIZE} eq '0'; } } return; } # End of domain_update sub checklibs { #--------------------------------------------------------------------------------# This routine does a basic check to make sure all the necessary libraries have # been installed. #--------------------------------------------------------------------------------# my @libs; my $mesg; unless ($EMSinstall{BINONLY}) { $mesg = "Checking for missing system i386 libs needed to run the Domain Wizard GUI"; &emsprint(0,9,92,2,1,$mesg); my @bins=(); $ENV{LD_LIBRARY_PATH} = "$EMSinstall{EMSDIR}/domwiz/libs/jre1.6.0_11/lib /i386"; push @bins => "$EMSinstall{EMSDIR}/domwiz/libs/jre1.6.0_11/bin/java";

push @bins => "$EMSinstall{EMSDIR}/domwiz/libs/jre1.6.0_11/lib/i386/libj awt.so"; push @bins => "$EMSinstall{EMSDIR}/domwiz/libs/jre1.6.0_11/lib/i386/xawt /libmawt.so"; &emsprint(5,11,92,1,0,"Checking Java libs -"); @libs = &libcheck(@bins); if (@libs) { &emsprint(0,1,12,0,1," Missing i386 System Libraries"); &emsprint(0,11,144,1,0,$_) foreach @libs; if ($EMSinstall{XBIN} eq 'x64') { $mesg = "You will need to install the missing i386 system librar ies on your 64-bit machine before running ". "the Domain Wizard GUI. The i386 (32-bit) libs are norma lly located in the /usr/lib directory ". "and not the /usr/lib64 directory. Note that when insta lling the libs in your system you ". "may have to specify the i386 version."; } else { $mesg = "You will need to install the missing i386 system librar ies on your machine before running ". "the Domain Wizard GUI. The i386 (32-bit) libs are norma lly located in the /usr/lib directory."; } &emsprint(6,11,92,2,2,$mesg); $mesg = "So, you have some work to do before running dwiz [Ya, ya, I know] "; &emsprint(0,14,92,1,0,$mesg); my $ans = <>; chomp $ans; } else { &emsprint(0,1,12,0,2," You're good to go!"); } } my @libs; $mesg = "Checking for missing system libs needed for some utility packages"; &emsprint(0,9,92,1,1,$mesg); &emsprint(5,11,92,1,0,"Checking ncview routine -"); my @bins = qw (ncview); my @list=(); foreach (@bins) { push @list => "$EMSinstall{EMSDIR}/util/bin/$_" if -e "$EMSinstall{EMSDI R}/util/bin/$_"; } @libs = @list ? &libcheck(@list) : (); if (@libs) { &emsprint(0,1,12,0,1," Missing System Libraries"); &emsprint(0,11,92,1,0,$_) foreach @libs; $mesg = "Not critical, but you will need to install the missing i386 sys tem libraries before using the ncview routine."; &emsprint(6,7,92,2,2,$mesg); } else { &emsprint(0,1,12,0,1," You're good to go!"); } &emsprint(5,11,92,1,0,"Checking GrADS routines -");

my @bins = qw (gribmap grads gxtran gribscan); my @list=(); foreach (@bins) { push @list => "$EMSinstall{EMSDIR}/util/grads/bin/$_" if -e "$EMSinstall {EMSDIR}/util/grads/bin/$_"; } unless (@list) { &emsprint(0,1,12,0,1," Failed"); &emsprint(0,7,92,1,0,"Missing GrADS executables. Was there a problem wit h the installation?"); } @libs = @list ? &libcheck(@list) : (); if (@libs) { &emsprint(0,1,12,0,1," Missing System Libraries"); &emsprint(0,11,92,1,0,$_) foreach @libs; $mesg = "Not critical, but you will need to install the missing i386 sys tem libraries before using GrADS routines."; &emsprint(6,7,92,2,2,$mesg); } else { &emsprint(0,1,12,0,1," You're good to go!"); } &emsprint(5,11,92,1,0,"Checking GEMPAK routines -"); my @bins = qw (dcgrib2 nagrib gdcntr gdmap gdlist gdplot3 gdplot_gf); my @list=(); foreach (@bins) { push @list => "$EMSinstall{EMSDIR}/util/nawips/os/linux/bin/$_" if -e "$ EMSinstall{EMSDIR}/util/nawips/os/linux/bin/$_"; } @libs = @list ? &libcheck(@list) : (); if (@libs) { &emsprint(0,1,12,0,1," Missing System Libraries"); &emsprint(0,11,92,1,0,$_) foreach @libs; $mesg = "Not critical, but you will need to install the missing i386 sys tem libraries before using NAWIPS/GEMPAK routines."; &emsprint(6,7,92,2,2,$mesg); } else { &emsprint(0,1,12,0,1," You're good to go!"); } return; } sub sysinfo { #--------------------------------------------------------------------------------# This routine attempts to gather information on the users system and print it out #--------------------------------------------------------------------------------# use Sys::Hostname; use Net::Ping;

use Net::hostent; use Socket; use POSIX "floor"; my %Sysinfo; my $mesg; $mesg = "Collecting system information so I can determine which binaries are best for you"; &emsprint(1,4,92,1,1,$mesg) unless ($EMSinstall{BINONLY} or ($EMSinstall{LIS T} and !$EMSinstall{LISTALL})); # Get hostname and IP information # my $hostl = `hostname`; chomp $hostl; $hostl = 'localhost' unless $hostl; my $h = gethost($hostl); unless ($h) { &emsprint(6,7,144,1,1,"Unknown host $hostl"); $mesg = "It appears that your system is not familiar with hostname $host l. This may be due to it ". "being a stand alone system with no IP address assigned to $host l. You can correct ". "this potential problem by placing an entry in the /etc/hosts fi le; however, for now I will ". "use the \"localhost\" IP address."; &emsprint(0,10,92,0,1,$mesg); $h = gethost('localhost'); } my $host1 = $h->name; my $addr0 = inet_ntoa($h->addr); my $ip = "None available"; unless (system "host $host1 >& /dev/null") { my @hi = split / +/ => `host $host1`; $ip = $hi[$#hi]; } $Sysinfo{hostname} $Sysinfo{hostname1} $Sysinfo{address} $Sysinfo{address1} = = = = $hostl; $host1 ne $hostl ? $host1 : "None"; $addr0; $ip;

# Get OS information # $Sysinfo{os} = `/bin/uname`; return "Non Linux System" unless $Sysinfo{os} =~ /linux/i; $Sysinfo{kernel} = `/bin/uname -r`; $Sysinfo{type} = `/bin/uname -m`; # # my my if Check the kernel to make sure it is up-to-date

@k = split /\./ => $Sysinfo{kernel}, 3; $k = "$k[0]\.$k[1]"; ($k < 2.6) { $mesg = "The EMS installer detected the kernel version $k on your system , which appears to be ". "older than the version 2.6 that is the necessary for running th e STRC-compiled binaries. ".

"Continuing with the install but you may have to update your Lin ux distribution."; &emsprint(6,9,84,1,2,"Old Man Kernel?!",$mesg); } my $date = gmtime(); chomp $date; $Sysinfo{date} = "$date UTC"; # Try to determing the distro information # my $distro; my @files = qw (redhat-release fedora-release debian_version UnitedLinux-rel ease SuSE-release slackware-version mandrake-release gentoo-release); foreach (@files) {$distro = `cat /etc/$_` if -e "/etc/$_";} $distro = `cat /etc/*-release` unless $distro; $Sysinfo{distro} = $distro ? $distro : "Unknown Distribution"; chomp $distro ; # Get preferred binary type for system based on SSE instruction set on CPU # according to cpuinfo utility. # my $tbin; my $tcores; ($tbin, $tcores) = &target; my $tbits = ($tbin =~ /x64/) ? 'x64' : 'x32'; $Sysinfo{binary} = $EMSinstall{XBIN} ? "Target Binary $EMSinstall{XBIN} (Req uested)" : "Target Binary $tbin"; $Sysinfo{reqbin} = "Target Binary $EMSinstall{BINONLY}" if $EMSinstall{BINON LY}; my $btrgt = 'Unknown'; if ($EMSinstall{UPDATE} $btrgt = 'athlonxp' $btrgt = 'barcelona' $btrgt = 'core2' $btrgt = 'k8' $btrgt = 'p7' $btrgt = 'penryn' $btrgt = 'piv' $btrgt = 'px' and -e $ENV{EMS_BIN} and !$EMSinstall{XBIN}) { if -e "$ENV{EMS_BIN}/.athlonxp"; if -e "$ENV{EMS_BIN}/.barcelona"; if -e "$ENV{EMS_BIN}/.core2"; if -e "$ENV{EMS_BIN}/.k8"; if -e "$ENV{EMS_BIN}/.p7"; if -e "$ENV{EMS_BIN}/.penryn"; if -e "$ENV{EMS_BIN}/.piv"; if -e "$ENV{EMS_BIN}/.px";

$btrgt = 'x32' if -e "$ENV{EMS_BIN}/.x32"; $btrgt = 'x64' if -e "$ENV{EMS_BIN}/.x64"; $Sysinfo{binary} = "Target Binary $btrgt (Installed)"; $EMSinstall{XBIN} = ($btrgt eq 'Unknown') ? $tbin : $btrgt; } # Estimate the number of CPUs and cores the old fashion way. This is someti mes # a problem if use has hyperthreading turned ON. # # $tprocs - Total number of processors # $pprocs - Total number of physical CPUs # $tcores - Total number of cores per Physical CPU # my @cores = (); my $tprocs = 0; my $pprocs = 0;

my $siblngs= 0; my $ncores = 0; $Sysinfo{coreid} = 0; if ( -e "/proc/cpuinfo" ) { open FILE => "/proc/cpuinfo";my @lines foreach (@lines) { s/\n//; if ( s/^\s*(processor)\s*://i ) if ( s/^\s*(cpu cores)\s*://i ) if ( s/^\s*(siblings)\s*://i ) if ( s/^\s*(core id)\s*://i ) if ( s/^\s*(model name)\s*://i ) if ( s/^\s*(cpu MHz)\s*://i ) } } $tcores+=0; $tprocs+=0; $pprocs+=0;

= <FILE>;close FILE; {$tprocs++;} {$tcores = $_;} {$siblngs = $_;} {$_+=0;push @cores => $_;} {s/ +/ /g;$Sysinfo{name} = $_;} {$Sysinfo{speed} = $_;}

@cores = &rmdups(@cores); @cores = sort {$a <=> $b} @cores; $ncores = scalar @cores ? scalar @cores : $tcores; $ncores = $tprocs unless $ncores; # Determine whether hyperthreading is turned ON, which should be true # if #siblings != cpu cores # my my my my $ht = ($siblngs != $tcores) ? 1 : 0; $vcpus = $ht ? int ($tprocs*0.5) : $tprocs; $pcpus = $vcpus / $ncores; $cpcpu = $ncores;

if ( -e "/proc/meminfo" ) { open FILE => "/proc/meminfo";my @lines = <FILE>;close FILE; foreach (@lines) {s/\n//; if ( s/^\s*(MemTotal)\s*://i ) { $Sysinfo{me mory} = $_;} } $Sysinfo{memory} =~ s/[a-z]+//i; $Sysinfo{memory} = floor ($Sysinfo{memory}/1024); } while ( my ( $key, $vals ) = each %Sysinfo ) { $vals =~ s/\n//; $vals =~ s/^\s+//; $Sysinfo{$key} = $vals; } $ht = $ht ? 'On' : 'Off'; my $sysinfo = "System Information for " System Date " Alternate Hostname " Machine Address " Alternate Address " Machine OS " Kernel " Linux Distribution " CPU Name " CPU Type " CPU Instructions " Physical CPUs $Sysinfo{hostname}\n\n". : $Sysinfo{date}\n". : $Sysinfo{hostname1}\n". : $Sysinfo{address} \n". : $Sysinfo{address1} \n". : $Sysinfo{os} \n". : $Sysinfo{kernel} \n". : $Sysinfo{distro} \n". : $Sysinfo{name} \n". : $Sysinfo{type} \n". : $tbin \n". : $pcpus \n".

$sysinfo = l{BINONLY}; # # # file. # # my if

" Cores per CPU " Total Processors " Hyper-Threading " CPU Speed (MHz) " System Memory " Binaries "$sysinfo\n". " Requested Binaries

: : : : : :

$cpcpu \n". $vcpus \n". $ht\n". $Sysinfo{speed} \n". $Sysinfo{memory} Mb\n". $Sysinfo{binary} "; " if $EMSinstal

: $Sysinfo{reqbin}

While we are here let's make sure the .mpd.conf file exists Create the necessary "secretword=emsuser" entry in the user's ~/.mpd.conf This step is necessary for running MPICH2 although I have no idea why @user = getpwuid $<; (defined $user[7] and !-e "$user[7]/.mpd.conf") { system "echo 'secretword=emsuser' > $user[7]/.mpd.conf"; system "echo 'MPD_PORT_RANGE=50001:59999' >> $user[7]/.mpd.conf"; system "chmod 600 $user[7]/.mpd.conf";

} $tbits = $EMSinstall{XBITS} if $EMSinstall{XBITS}; $tbin = $EMSinstall{XBIN} if $EMSinstall{XBIN}; return ($tbin,$tbits,$pcpus,$cpcpu,$sysinfo); } sub check_http { #---------------------------------------------------------------------------------# This routine checks to make sure you can use http to access the necessary # information on the outside server. #---------------------------------------------------------------------------------# my $mesg; my $host = shift; # Can I connect to the server? # if (&netcheck($host)) { if ($EMSinstall{ICONF}) { $mesg = "There appears to be a problem connecting to:\n\n". " $host,\n\n". "which is the EMS update server. If this is an existing ins tallation then the ". "server is defined by the UPDATEHOST parameter in $EMSinsta ll{ICONF}.\n\n". "Maybe the server has changed and nobody told you or maybe you don't have ". "a connection to the outside world? Either way, you are not getting anything ". "from me until the problem is resolved."; } else {

$mesg = "There appears to be a problem connecting to:\n\n". " $host,\n\n". "which is the EMS update server. Maybe the server has chang ed and ". "nobody told you or maybe you don't have a connection to th e outside world? ". "Either way, you are not getting anything from me until the problem is resolved."; } &ems_inspire($mesg); return 1; } return; } sub help { #--------------------------------------------------------------------------------------------# STRC WRF Installation Script help menu #--------------------------------------------------------------------------------------------# my ($exe,@badopts) = @_; my $mesg; # Handle any bad options that might have been passed # &bad_option($exe,@badopts) if @badopts; $mesg = "WRF Environmental Modeling System (EMS) Install'n & Update'n Routin e"; &emsprint(0,2,84,2,1,$mesg); $mesg = "USAGE: \n\n". " % $exe [semi-manditory verbiage] [stuff you may not know about]\n \n\n". "RUDIMENTARY INFORMATION OF THE BASIC KIND"; &emsprint(0,4,84,1,1,$mesg); $mesg = "The $exe routine handles all your WRF EMS installation and updating needs, even those of which ". "you were not aware. This routine is more powerful than you can imag ine. Sometimes, it will just ". "knows what you want, although whether it wants to comply depends up on whether $exe has been treated ". "with love and affection. Just remember, as with all WRF EMS routine s (and life too), it puts out what ". "you put in."; &emsprint(0,6,84,1,1,$mesg); $mesg = "While there are an infinite number of options that you can try with $exe, the list below contains ".

"those options that will actually work, so you're better off startin g there before \"go'n rogue\" ". "and attempting something that can have serious consequenses.\n\nLis ten to your mother and the WRF EMS."; &emsprint(0,6,84,1,1,$mesg); &emsprint(0,4,84,2,1,"BECAUSE YA GOTTA START SOMEWHERE"); $mesg = "The novice $exe user should embrace its most basic of functions:\n\ n". " % $exe --release [release version]\n". "Or\n". " % $exe --update [release version]\n\n". "The release version is optional as the default is the most current release.\n\nAgain, the $exe knows ". "more than you do."; &emsprint(0,6,84,1,1,$mesg); $mesg = "And as if it hasn't done enough for you already; look at, but don't touch, what else the $exe can do:\n\n". " % $exe --list\n\n". "Which will give you a listing of available EMS releases and updates provided there are any."; &emsprint(0,6,84,1,1,$mesg); $mesg = "OTHER AVAILABLE OPTIONS - BECAUSE YOU ASKED NICELY AND I'M BEGINNIN G TO LIKE YOU\n\n". " Option Argument Usage Description\n". " [optional] \n"; &emsprint(0,4,96,2,1,$mesg); $mesg = "--list general Provide a listing of available releases and updates on the STRC server"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--listall general Provide a verbose listing of av ailable releases and updates on the STRC server"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--version general Print the EMS install routine r elease number and get out"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--release [RELEASE] install'n tallation action - same as \"--install\""; &emsprint(0,6,144,1,1,$mesg); $mesg = "--install [RELEASE] install'n tallation action - same as \"--release\""; &emsprint(0,6,144,1,1,$mesg); $mesg = "--reldir SOMEDIR install'n directory) of the EMS release files on the local &emsprint(0,6,144,0,1,$mesg); $mesg = "--domtrans [SOMEDIR] install'n Tell the $exe you want some ins Tell the $exe you want some ins Override the default location ( system"; Tranfer existing computational

domains located in SOMEDIR to new installation"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--target ARCH install'n Download/install only the speci fied target binaries"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--scour install'n Delete the existing EMS install ation rather than saving it"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--nogeog install'n Don't download and install the large WRF static GEOG files"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--nowkp install'n Don't download and install the classroom exercises"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--update [RELEASE] update'n ate'n action"; &emsprint(0,6,144,1,1,$mesg); $mesg = "--updir SOMEDIR update'n directory) of the EMS update files"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--force update'n date even though it's already installed"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--binonly ARCH update'n fied runtime routines (wrfm.exe & real.exe)"; &emsprint(0,6,144,0,1,$mesg); # $mesg = "--revert RELEASE update'n ck to a previously installed release"; # &emsprint(0,6,144,0,1,$mesg); Tell the $exe you want some upd Override the default location ( Force the installation of an up Download/install only the speci Chickened out - I want to go ba

$mesg = "--emsdir EMSDIR both Top level of the installed WRF EMS (E.g.: --emsdir /usr1/wrfems)"; &emsprint(0,6,144,1,1,$mesg); $mesg = "--repodir SOMEDIR both Directory where the releases or updates reside locally (SOMEDIR/<release>)"; &emsprint(0,6,144,1,1,$mesg); $mesg = "--binlist both List the supported target binar ies"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--tplist both List the supported target binar iesi just like --binlist"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--noinstall both Do Not install the downloaded f iles (Default is install)"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--nolocal both Don't use tar files found local ly in wrfems/release or wrfems/updates - Get'm server fresh"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--host HOSTNAME both The hostname or IP of the WRF E MS file server"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--x64 both Download/install the x64 64-bit binaries regardless of the system architecture"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--x32 both Download/install the x32 32-bit binaries regardless of the system architecture"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--piv both Download/install the xp4 32-bit

binaries regardless of the system architecture"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--px both Download/install the generic i3 86 binaries regardless of the system architecture"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--match STR,STR, both A list of comma separated chara cter strings used to limit files to download"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--nomatch STR,STR, both A list of comma separated chara cter strings used to limit files to download"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--[no]localize both [Do Not] relocalize existing co mputational domains"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--wget both Use only the wget routine for h ttp requests to the STRC server"; &emsprint(0,6,144,0,1,$mesg); $mesg = "--curl both Use only the curl routine for h ttp requests to the STRC server"; &emsprint(0,6,144,0,1,$mesg); $mesg = "And most importantly:\n\n". " % $exe --help For help, love, understanding, and this menu ag ain"; &emsprint(0,4,108,1,3,$mesg); exit; } sub bad_option { #--------------------------------------------------------------------------------# Process any inappropriate options that may have been passed by the user #--------------------------------------------------------------------------------# my ($exe,@badopts) = @_; my $str = @badopts > 1 ? 'are not options' : 'is not an option'; my $mesg = "Hey, did you know that \"@badopts\" $str to $exe?\n\nTry again o r run \"$exe --help\" ". "for assistance.\n\nRemember, there are no bad options, just thos e that will ". "result in this message again."; &ems_inspire($mesg); &emsprint(0,1,1,0,2," "); exit; } sub libcheck { #--------------------------------------------------------------------------------# This routine accepts a list of dynamic binary routines and an returns # a list of missing libraries on the system. #--------------------------------------------------------------------------------# my @libs;

my @routines = @_; my $ldd = `which ldd`; chomp $ldd; $ldd = "/usr/bin/ldd" unless -e $ldd; exit unless -e $ldd; foreach (@routines) { next unless $_; foreach (grep /not found/i => `$ldd $_`) { chomp; s/\s//g; split /=/; push @libs => $_[0]; } } # Eliminate duplicates # @libs = &rmdups(@libs); return @libs; } sub rmdups { #--------------------------------------------------------------------------------# This routine eliminates duplicates from a list. #--------------------------------------------------------------------------------# my @list = @_; my %temp = (); @list = grep ++$temp{$_} < 2 => @list; @list = sort @list; return @list; } sub emsprint { #--------------------------------------------------------------------------------# This routine prints all error, warning, and information statements to the # user with a consistent format. #--------------------------------------------------------------------------------# use Text::Wrap; my ($type,$indnt,$cols,$leadnl,$trailnl,$head,$body,$text) = @_; return if $ENV{VERBOSE} <= 0; # Set defaults # local $Text::Wrap::columns = $cols > 80 ? $cols : 80; # sets the wrap point . Default is 80 columns. local $Text::Wrap::separator="\n"; local $Text::Wrap::unexpand;

my $nl = "\n"; $indnt = ! $indnt ? 6 : $indnt < 0 ? 6 : $indnt; $leadnl = $leadnl < 0 ? sprintf ("%s",$nl x 1) : sprintf ("%s",$nl x $lead nl); $trailnl = $trailnl < 0 ? sprintf ("%s",$nl x 1) : sprintf ("%s",$nl x $trai lnl); $type = $type == 1 ? '*' : RROR " : : : ""; $text = $text ? " ($text)" $type == 2 ? "EMS WARNING" : $type == 3 ? "EMS E $type == 4 ? "EMS DEBUG " : $type == 5 ? '->' $type == 6 ? '!' : $type == 7 ? '>' : "";

# Format the text # my $header = $type eq '*' ? "$type$text " : $type eq '!' ? "$type$text " : $type eq '->' ? "$type$text " : $type eq '>' ? "$type$text " : $type ? "$type$ text: " : ""; $head = "$header$head"; $body = "\n\n$body" if $body; # Format the indent # my $hindnt = $indnt < 0 ? sprintf ("%s"," " x 1) : sprintf ("%s"," " x $indn t); my $bindnt = sprintf ("%s"," " x length "$hindnt$header"); my $windnt = $type eq '*' ? " $hindnt" : $type eq '->' ? " $hindnt" : $ty pe eq '>' ? " $hindnt" : $type eq '!' ? " $hindnt" : $bindnt; $| = 1; print "$leadnl"; print wrap($hindnt,$windnt,$head); print wrap($bindnt,$bindnt,$body) if $body; print "$trailnl"; return; }

sub locate { #-------------------------------------------------------------------------------# Routine to locate a linux method #-------------------------------------------------------------------------------# my $rutil = shift; my $util = `whereis $rutil`; my @utils = split / / => $util; return $utils[1] if $utils[1] and -X $utils[1]; $rutil = -e "/usr/bin/$rutil" ? "/usr/bin/$rutil" : -e "/bin/$rutil" ? "/bin /$rutil" : 0 unless -X $rutil; return $rutil;

} sub httpget { #-------------------------------------------------------------------------------# Routine uses the specifies http command utility to download a file from # the STRC servers. #-------------------------------------------------------------------------------# my $mesg; return 1 if &mkdir("$EMSinstall{EMSDIR}/logs"); my $dlog = "$EMSinstall{EMSDIR}/logs/http_download.log"; &rm($dlog); my ($rfile,$lfile,$util) = @_; &rm($lfile); my $hutil = &popit($util); $|=1; my $cmd = ($util =~ /curl/) ? "$util -v -C - -s --connect-timeout 25 --max-t ime 1800 $rfile -o $lfile >& $dlog" : ($util =~ /wget/) ? "$util -a $dlog -v -t 25 -T 25 --read-timeout= 1800 --connect-timeout=10 -O $lfile $rfile" : 0; return 1 unless $cmd; # print "CMD: $cmd\n"; my $lsfile = &popit($lfile); # &emsprint(1,6,144,1,0,"Using $hutil to get $lsfile from $EMSinstall{UPDATEHO ST} -"); if (system "$cmd") { my $err = $?; &rm($lfile); &int_handle if $err == 2; &emsprint(0,1,12,0,1," Failed"); my $err; if (-e $dlog) { open INFILE => "$dlog"; while (<INFILE>) { $err = "$err $_";} close INFILE; } $mesg = "There was a problem retrieving file from $EMSinstall{UPDATEHOST }"; &emsprint(6,8,144,1,1,$mesg); &emsprint(0,11,144,1,0,$err) if $err; return 1; } return; } sub unpack { #-------------------------------------------------------------------------------# Routine to unpack the specified tar file.

#-------------------------------------------------------------------------------# my ($file, $dir) = @_; unless (-e $file) { &emsprint(6,9,144,1,2,"File not found - $file"); return 1; } if ($file =~ /tgz$/i) { if (system "tar -xzf $file -C $dir") { &int_handle if $? == 2; &emsprint(6,9,144,1,2,"Problem unpacking it"); &emsprint(0,9,144,1,2,"Command: tar -xzf return 1; } } elsif ($file =~ /tbz$/i) { if (system "tar -xjf $file -C $dir") { &int_handle if $? == 2; &emsprint(6,9,144,1,2,"Problem unpacking it"); &emsprint(0,9,144,1,2,"Command: tar -xjf return 1; } } system "chmod -R 755 $dir"; return; }

$file\n\n Message: $! - Ex $file -C $dir");

$file\n\n Message: $! - Ex $file -C $dir");

sub rm { #-------------------------------------------------------------------------------# Routine to delete a specified file. #-------------------------------------------------------------------------------# my $status; for (shift) { if (-d $_) { $status = system "rm -fr $_"; } elsif (-f $_ or -l $_) { $status = system "rm -f $_"; } } return $status } sub mkdir { #-------------------------------------------------------------------------------# Routine to create a specified directory. #-------------------------------------------------------------------------------# my $dir = shift; my $status = system "mkdir -p $dir" unless -e $dir; return $status }

sub target { #--------------------------------------------------------------------------------# This routine determined the target CPU on the local system #--------------------------------------------------------------------------------# use Switch; # Get preferred binary type for system based on SSE instruction set on CPU # according to cpuinfo utility. # my $x = (`uname -i` =~ /64/) ? 'x64' : 'x32'; # The cpuid routine may not be installed yet so just guess # my $p=0; return ($x, $p) unless -e "$EMSinstall{EMSDIR}/util/bin/cpuid"; my ($u, $t); my @lines = `$EMSinstall{EMSDIR}/util/bin/cpuid`; chomp foreach @lines; foreach (@lines) { ($u, $t) = split /:/ => $_, 2 if /type/i; ($u, $p) = split /:/ => $_, 2 if /processor count/i; } $t =~ s/ +//g; $t =~ s/-tp//g; $t =~ s/-64//g; $t = 'piv' unless $t; $t = 'x64' if $x eq 'x64'; $p =~ s/ +//g; $p = 1 unless $p; my $target; switch ($t) { case /x64/i case /p5|px|p6|k6|p3|piii/ case /athlon|athlonxp|p7|p4|piv|core2/ else }

{$target {$target {$target {$target

= = = =

'x64'} 'px'} 'piv'} 'x32'}

# Return the target CPU type and number of cores # return ($target, $p); } sub popit { #--------------------------------------------------------------------------------# This routine accepts the fully qualified path/name and returns just # the name of the file or what ever was at the end if the string. #--------------------------------------------------------------------------------# my $path = shift; $path =~ s/\^.//g; my @list = split /\// => $path; return pop @list; } sub popit2 {

#--------------------------------------------------------------------------------# This routine accepts the fully qualified path/name and returns both # the name of the file and the path. #--------------------------------------------------------------------------------# for (shift) { s/\^.//g; my @list = split /\// => $_; my $prog = pop @list; my $path = join "/" => @list; return $path, $prog; } } sub method { #--------------------------------------------------------------------------------# This routine determines which linux utility to use to send the http commands # to the EMS servers. The currently supported utilities are wget and curl alth ough # others may be added later. The routine checks if the executables are availabl e on # the local system and returns an error if not found. #--------------------------------------------------------------------------------# my $mesg; my $meth = shift; if ($meth) { # user requested method # Did the user specify the fully qualified path? # my @list = split /\// => $meth; return $meth if $#list > 0 and -X $meth; # Only the name of the method was provided. Locate it. # $mesg = "The requested http command utility, $meth, does not appear to b e available on ". "this system. Or did I miss something?"; $meth = &locate($meth); } else { # No user-specified utility my @utils = qw(wget curl); # Note that curl is the default $meth = &locate($_) foreach @utils; my $list = join " nor " => @utils; $mesg = "It appears that neither the $list utilities are available on yo ur system. ". "At least one of these linux routines must be available to autom atically ". "download files from the WRF EMS server"; } &emsprint(3,8,88,1,1,$mesg) unless $meth;

return $meth; } sub netcheck { #--------------------------------------------------------------------------------# This routine does some basics checks to determine whether the WRF EMS server # is accessible from the local system. # # Input: # $host - hostname of the remote system # # Return: # 1 (fail) or 0 (success) # #--------------------------------------------------------------------------------# use Sys::Hostname; use Socket; my $host = shift; # Does the network know of the host? # unless (gethost($host)) { my $mesg = "No such host - $host"; &emsprint(3,4,96,2,1,$mesg); return 1; } # # # # # if Is the host reachable? Turned off since the COMET servers do not always respong to a ping in fear of a "smurf DNS attack." Damn those little blue guys! (system "ping -q -c 2 $host >& /dev/null") { my $mesg = "Host Not Available - $host"; &emsprint(3,4,96,2,1,$mesg); return 1;

# # # # #

return; } sub read_conf { #--------------------------------------------------------------------------------# This routine reads the contents of the input configuration files and # returns a hash containing the parameter and value #--------------------------------------------------------------------------------# # my @nouser = qw (RA_LW_PHYSICS RA_SW_PHYSICS DXDT_NMM DXDT_ARW TIME_STEP_SOU ND STEP_TO_OUTPUT_TIME TARGET_CFL MAX_STEP_INCREASE_PCT STARTI NG_TIME_STEP MAX_TIME_STEP MIN_TIME_STEP RA_CALL_OFFSET EXPORT LEVELS);

my $filename = shift; my $exp = $filename =~ /export/i; open INFILE, $filename; my %hash; my @list; my $pvar; while (<INFILE>) { tr/\000-\037/ /; s/^\s+//g; next if /^#|^$|^\s+/; s/ //g unless /MPIRUNARGS/; s/\t//g;s/\n//g; if (/\s*=\s*/) { my ($var, $value) = split(/\s*=\s*/, $_, 2); if ($exp) { push @list => $value; } else { $var = uc $var; next if (grep /^$var$/, @nouser); $hash{uc $var} = $value; } } } close INFILE; return $exp ? @list : %hash; } sub get_avails { #--------------------------------------------------------------------------------# A routine to request a list of EMS updates and full releases available # for installation. Upon successful completion the available updates and # releases will be located in the $EMSinstall{UPDATES} and $EMSinstall{RELEASE S} # hashes respectively. #--------------------------------------------------------------------------------# my $mesg; my @avails; my %emshosts; # Define the EMS servers # $emshosts{EMS1} = 'emsdata1.comet.ucar.edu'; $emshosts{EMS2} = 'emsdata2.comet.ucar.edu'; $emshosts{STRC} = 'soostrc.comet.ucar.edu'; my @hosts = keys %emshosts; $EMSinstall{UPDATEHOST} = $EMSinstall{UPDATEHOST} ? $EMSinstall{UPDATEHOST} : $emshosts{$hosts[int (rand 3)]}; # Set the default server if it has not been previously defined

# $EMSinstall{UPDATEHOST} = $EMSinstall{REPODIR} ? 'local' : $EMSinstall{DVD} ? 'local' : $EMSinstall{UPDATEHOST} ? $EMSinstall{UPDATEHOST} : 'soostrc.comet.ucar.edu'; $EMSinstall{UPDATEHOST} = '128.117.110.214' if $EMSinstall{UPDATEHOST} eq 's oostrc.comet.ucar.edu'; # If the user passed the --repodir option then it is assumed that # the necessary files exist on the local host. # if ($EMSinstall{REPODIR}) { # Make sure the tarfile directory exists # unless (-e $EMSinstall{REPODIR}) { $mesg = "You have passed the \"--repodir\" option that specifies th at the update or ". "release files be found locally. This option requires that the tar files be ". "located in the $EMSinstall{REPODIR}/<release> directory; h owever, I am unable ". "to find this directory.\n\nWhat's up with that?!"; &ems_inspire($mesg); return 1; } } elsif ($EMSinstall{DVD}) { # Make sure the tarfile directory exists # unless (-e $EMSinstall{REPODIR}) { $mesg = "You have passed the \"--repodir\" option that specifies th at the update or ". "release files be found locally. This option requires that the tar files be ". "located in the $EMSinstall{REPODIR}/<release> directory; h owever, I am unable ". "to find this directory.\n\nWhat's up with that?!"; &ems_inspire($mesg); return 1; } } else { # Get the information from the EMS server via http # Do I have a utility to send the http commands? # $EMSinstall{UTIL} = $EMSinstall{WGET} ? 'wget' : $EMSinstall{CURL} ? 'cu rl' : 0; $EMSinstall{UTIL} = &method($EMSinstall{UTIL}); unless ($EMSinstall{UTIL}) { $mesg = "Unable to identify a linux utility to make the http request s ". "to the server. The standard utilities used are \"curl\" or \"wget\"; ". "however, they do not appear to be on your system. You will

need to ". "install them before continuing with life as you know it."; &ems_inspire($mesg); return 1; } # Check the status of the necessary http connection # return 1 if &check_http($EMSinstall{UPDATEHOST}); } # # # # # Upon a successful return from getlist, the available update and release files will be located in the $EMSinstall{UPDATES} and $EMSinstall{RELEASES} hashes respectfully. No sense passing the hashed back.

return 1 if &getlist($EMSinstall{UPDATEHOST}); return; } sub getlist { #--------------------------------------------------------------------------------# A routine to request a list of EMS updates and full releases available # for installation from an http server #--------------------------------------------------------------------------------# my $mesg; my $host = shift; my $rlog = (defined $ENV{EMS} and -e "$ENV{EMS}/logs") ? "$ENV{EMS}/logs/htt p_request.log" : "/tmp/http_request.log"; &rm($rlog); if ($host eq 'local') { # Begin by interrogating the contents of the $EMSinstall{REPODIR} and m ake # sure that the structure REPODIR/<release dir>. # We need the names of the updates indicated by update.* # or the names of the releases indicated by release.* # my @releases=(); opendir DIR => $EMSinstall{REPODIR}; foreach (readdir(DIR)) { push @releases => $_ unless ($_ eq "." or $_ eq ".."); } closedir DIR; my $ku = 'update'; my $kr = 'release'; my $kg = 'wrf.geog'; foreach my $reldir (@releases) { opendir DIR => "$EMSinstall{REPODIR}/$reldir"; foreach (readdir(DIR)) { chomp; next unless /^$ku|^$kr|^$kg/;

if (/^$ku/) { my $loc = "$EMSinstall{REPODIR}/$reldir/$_"; push @{$EMSinstall{UPDATES}{$reldir}} => $loc; } else { my $loc = "$EMSinstall{REPODIR}/$reldir/$_"; push @{$EMSinstall{RELEASES}{$reldir}} => $loc; } } } closedir DIR; } else { &emsprint(1,4,96,1,1,"Connecting to $host to get requested information") ; my $https = "http://$host"; my $cgi = "/cgi-bin/ems_info.pl"; my $cmd = "\"$https$cgi?list\""; # Define the commands to be used by wget and curl to retrieve the infor mation # $|=1; my $cmd = ($EMSinstall{UTIL} =~ /curl/) ? "$EMSinstall{UTIL} -q -s -f -connect-timeout 10 --max-time 30 $cmd >& $rlog" : ($EMSinstall{UTIL} =~ /wget/) ? "$EMSinstall{UTIL} -a /tmp/wge t.log -nv -t 3 -T 10 --read-timeout=1800 --connect-timeout=10 -O $rlog $cmd" : 0 ; return 1 unless $cmd; # Go query the server to get the information # if (system "$cmd") { &int_handle if $? == 2; # Let's run the command again in verbose mode to get some helpful i nformation. # my $cmd = ($EMSinstall{UTIL} =~ /curl/) ? "$EMSinstall{UTIL} -q -v f --connect-timeout 10 --max-time 30 $cmd >& $rlog" : ($EMSinstall{UTIL} =~ /wget/) ? "$EMSinstall{UTIL} -a /tmp /wget.log -v -t 3 -T 10 --connect-timeout=10 -O $rlog $cmd" : 0; &rm($rlog); system "$cmd"; my $err; if (-e $rlog) { open INFILE => "$rlog"; while (<INFILE>) {$err = "$err $_";} close INFILE; } $mesg = "There was a problem retrieving information from $EMSinstall {UPDATEHOST}"; &emsprint(6,8,144,1,1,$mesg); &emsprint(0,11,144,1,1,$err) if $err; return 1;

} else { # Apparent success or at least lets hope so # Begin by interrogating the log file to determine whether there wa s a normal result. # We need the names of the updates indicated by AVAILABLE UPDATE: < UPDATE> # or the names of the releases indicated by AVAILABLE RELEASE: <REL EASE> # my $ku = 'AVAILABLE UPDATE:'; my $kr = 'AVAILABLE RELEASE:'; open INFILE => "$rlog"; while (<INFILE>) { chomp; next unless /$ku|$kr/; if (s/$ku//g) { s/ //g; chomp; (my $rel, my $loc) = split /;/ => $_; next unless $rel and $loc; push @{$EMSinstall{UPDATES}{$rel}} => $loc; } elsif (s/$kr//g) { s/ //g; chomp; (my $rel, my $loc) = split /;/ => $_; next unless $rel and $loc; push @{$EMSinstall{RELEASES}{$rel}} => $loc; } } close INFILE; &rm($rlog); } } # If repodir return; } sub reconcile { #--------------------------------------------------------------------------------# A routine to list out the available EMS release information depending on the # options passed by the user. This is messy and needs to be cleaned up. #--------------------------------------------------------------------------------# my $mesg; my $dev; my $beta; my @list = @_; my $iver = shift @list; my @slist; my @flist = @list; # Keep the full list of updates/releases for comparison # Split the list up. # foreach (@list) { if (/dev$/i) { $dev = $_; } elsif (/beta$/i) { $beta= $_;

} else { push @slist => $_; } } # Eliminate the older releases from the list unless the user passed the --l istall option # @list=(); if ($iver =~ /\.beta$/) { # Current version is a beta release my $n=0; (my $biver = $iver) =~ s/\.beta$//g; foreach (@slist) { push @list => $_ unless $n; $n++ if $_ eq $biver; } } else { my $n=0; foreach (@slist) { $n++ if $_ eq $iver; push @list => $_ unless $n; } } @slist = @list; # Now handle update argument passed to the --update option # $EMSinstall{UPDATE} = $flist[0] if $EMSinstall{UPDATE} eq 'current'; #---------------------------------------------------------------------# Reconcile the requests for updates and installations # Handle the following update requests: # # Current Release Update Request Release Allowed? # ----------------------------------------------------------------# Beta Regular # Beta Development # Regular Beta Yes # Development Beta No # Beta Beta No # # Development Regular # Regular Development # Development Development # # Regular Regular #---------------------------------------------------------------------# # Does the requested update release actually exist? # unless (grep /^$EMSinstall{UPDATE}$/ => @flist) { $mesg = "Fantasy Update: $iver -> $EMSinstall{UPDATE}\n\n". "It appears that you are attempting to install a non-existent up date, ". "$EMSinstall{UPDATE}. You can use the \"--list\" option to list out ". "any updates or releases for which you are eligible."; &ems_inspire($mesg);

return 1; } if ($iver eq $EMSinstall{UPDATE}) { unless ($EMSinstall{FORCE} or $EMSinstall{BINONLY}) { $mesg = "Hey, the requested update, $iver, is the same as that alrea dy installed ". "on the local system. If you are true about your intent then use the \"--force\" ". "option to tell me that you really, really mean care."; &ems_inspire($mesg); return -1; } @slist=(); push @slist => $EMSinstall{UPDATE}; return @slist; } # # # # # # # # my my my Some $rbv $cbv $ibv $rfv $cfv $ifv information we will need along the way for the user -> Requested Base Release <wrf version>.<ems major> -> Current Base Release -> Installed Base Release -> Requested Full Release <wrf version>.<ems major>.<ems minor> -> Current Full Release -> Installed Full Release

@cbv = split /\./ => $flist[0]; my $cbv = join ".", @cbv[0..3]; @ibv = split /\./ => $iver; my $ibv = join ".", @ibv[0..3]; @rbv = split /\./ => $EMSinstall{UPDATE}; my $rbv = join ".", @rbv[0..3];

my @cfv = split /\./ => $flist[0]; my $cfv = join ".", @cfv[0..4]; my @ifv = split /\./ => $iver; my $ifv = join ".", @ifv[0..4]; my @rfv = split /\./ => $EMSinstall{UPDATE}; my $rfv = join ".", @rfv[0..4]; # Start with the request to update to/from a Beta release # if ($EMSinstall{UPDATE} =~ /beta$/i or $iver =~ /beta$/i) { # Beta to Beta release update only allowed if non-beta version # of installed beta release is available. # if ($EMSinstall{UPDATE} =~ /beta$/i and $iver =~ /beta$/i) { # Beta to B eta unless ($EMSinstall{FORCE}) { unless (grep /$ifv/ => @slist) { # Missing full update releases $mesg = "Updating No, No: $iver -> $EMSinstall{UPDATE}\n\n". "I bet you didn't know, but Beta -> Beta updates are not allowed ". "unless the full non-beta version of the installed r elease, which ". "in this case is $ifv, is available.\n\n". "Why not? Because life is not fair, that's why not. \n\n". "Your best and easiest solution may be to do a new i nstall of the $cfv ". "release with the \"--release $cfv\" option.";

&ems_inspire($mesg); return 1; } # requesting beta release when full release is available # if (grep /$rfv/ => @slist) { # Missing full update releases $mesg = "Updating No, No: $iver -> $EMSinstall{UPDATE}\n\n". "I bet you didn't know, but Beta -> Beta updates are not allowed ". "when the full non-beta version of the requested rel ease, which ". "in this case is $rfv, is available.\n\n". "Why not? Because life is not fair, that's why not. \n\n". "Simply make your life easier by updating to the ful l release."; &ems_inspire($mesg); return 1; } } # Attemptng to "update" to an earlier release # if (&rel_frmt($rfv,$ifv) < 0) { # Update release is earlier $mesg = "Updating Oxy Moron: $iver -> $EMSinstall{UPDATE}\n\n". "You should know that you can not \"Update\" to an earli er release. ". "You can, however, use the \"--revert\" option to accomp ish this task ". "provided that you still have the previous updates in th e \"updates\" ". "directory.\n\n". "Good Luck - You will need it."; &ems_inspire($mesg); return 1; } # So far So good - Append the beta release to the list # of updates needed and return. # unshift @slist => $EMSinstall{UPDATE}; } elsif ($EMSinstall{UPDATE} =~ /beta$/i and $iver =~ /dev$/i) { # Dev to beta # Update to a beta release from either a full or development release # $mesg = "Updating from a Development to Beta release\n\n". "I bet you didn't know, but you can only update a developmen t release ". "with another of the same release base level. Since you alre ady have ". "a development release installed, the only thing you can do to a fresh ". "install of $EMSinstall{UPDATE}.";

&ems_inspire($mesg); return 1; } elsif ($EMSinstall{UPDATE} =~ /dev$/i and $iver =~ /beta$/i) { # Beta to Dev # Update from a beta release to either a full or development release # unshift @slist => $EMSinstall{UPDATE}; } elsif ($EMSinstall{UPDATE} =~ /beta$/i) { # Full to Beta unshift @slist => $EMSinstall{UPDATE}; } # Last (default) is Beta to Full Nothing needed return @slist; } elsif ($EMSinstall{UPDATE} =~ /dev$/i or $iver =~ /dev$/i) { # Update to/from Development releases. Only 3 options: # Dev -> Dev # Full -> Dev # Dev -> Full # if ($ibv ne $rbv) { if ($EMSinstall{UPDATE} =~ /dev$/i and $iver =~ /dev$/i) { $mesg = "Different Base Levels ($ibv Vs. $rbv)\n\n". "I bet you didn't know, but you can only update a develo pment release ". "with another of the same release base level. For exampl e, you will need to ". "update your current installation to EMS version $flist[ 0] before updating to ". "development release $EMSinstall{UPDATE}.\n\n". "The development releases change regularly so come back often."; &ems_inspire($mesg); return 1; } elsif ($iver =~ /dev$/i) { # Current is Dev release $mesg = "Updating to Non-development Release\n\n". "I bet you didn't know, but you can only update a develo pment release ". "with another of the same release base level. Since you already have ". "a development release installed, the only thing you can do to a fresh ". "install of $EMSinstall{UPDATE}."; &ems_inspire($mesg); return 1; } push @slist => $EMSinstall{UPDATE}; return @slist; } @slist=(); push @slist => $EMSinstall{UPDATE}; return @slist; } # Reconsile the Full -> Full Requests

# if ( (grep /^$EMSinstall{UPDATE}$/ => @flist) and (!grep /^$EMSinstall{UPDAT E}$/ => @slist) ) { $mesg = "Updating DeJa Vu: $iver -> $EMSinstall{UPDATE}\n\n". "It appears that you are attempting to revert your system to a p revious release. ". "Please use the \"--revert <release>\" option for this task."; &ems_inspire($mesg); return 1; } my $n=0; my @list=(); my @olist = @slist; # preserve original list foreach (@slist) { $n = ($_ eq $EMSinstall{UPDATE}) ? $EMSinstall{UPDATE} ? $n+1 : 1 : $EMS install{UPDATE} ? $n : 0; push @list => $_ if $n; } @slist = @list; return @slist; } sub sort_release { #--------------------------------------------------------------------------------# A routine to sort the update and full release names. This task gets messy # as the names can not be correctly sorted by the Perl sort routines due to # the naming convention. Thus, some reformatting is necessary before we can # use the Perl sort utility. Also, return any beta and development releases # at the head of the list. #--------------------------------------------------------------------------------# my @list = sort @_; my %hash; my $dev; my $beta; foreach (@list) { my @rlist = split /\./ => $_; # Check if a beta release # if ($rlist[$#rlist] =~ /^b/i) { $beta = $_; next; } # Check if an development release # if ($rlist[$#rlist] =~ /^d/i) { $dev = $_; next; } # Reformat the names so that we can use the Perl sort

# foreach (@rlist) { $_+=0; $_ = "0$_" if length $_ == 1; } # The reformatted and original names will be placed # in a hash with the reformatted name being the key. # We will then sort on the keys and write the original # names to a new list. # my $ver = join "", @rlist; $hash{$ver} = $_ if $ver; } # We now have the hash so sort on the keys. The original # names will be written to the list from newest -> oldest (hopefully). # my @ordered; push @ordered => $hash{$_} foreach sort {$b <=> $a} keys %hash; # Add any development and beta releases to the beginning of the list # push @ordered => $beta if $beta; push @ordered => $dev if $dev; return @ordered; } sub rel_frmt { #--------------------------------------------------------------------------------# Reformat the release number for easier sorting and comparisons #--------------------------------------------------------------------------------# my $rv = shift; my @rv = split /\./ => $rv; foreach (@rv[0..4]) { $_+=0; $_ = "0$_" if length $_ == 1; } my $num = join "", @rv; return $num } sub rel_comp { #--------------------------------------------------------------------------------# Routine to check the whether one release is older or newer than one another # Return values are 1 ($ra newer than $rb), -1 ($rb newer than $ra), or 0 (same ) #--------------------------------------------------------------------------------# (my $ra, my $rb) = @_; unless ($ra and $rb) { my $mesg = "Missing release A ($ra) or B ($rb) in &rel_comp!";

&emsprint(3,6,88,3,1,$mesg); exit; } $ra = &rel_frmt($ra); $rb = &rel_frmt($rb); return $ra > $rb ? 1 : $rb > $ra ? -1 : 0;; } sub localize { #--------------------------------------------------------------------------------# Localize an existing domain #--------------------------------------------------------------------------------# use File::stat; my $domain = shift; my my my my my my $err $geogrid $static $log $wpsnl $wpsnlo = = = = = = int rand(1000); "$EMSinstall{EMSDIR}/bin/geogrid"; "$domain/static"; "$domain/log"; "$static/namelist.wps"; # my $nl = $wpsnl; "$static/namelist.wps.orig";

my $mesg; my $mesgs dards for ".

= "It appears that $domain does not meet the strict WRF EMS stan "a domain in need of localization.";

my %masternl; #### Add code to determine proper geog_data_res if not user defined #### my $dom = uc &popit($domain); $mesg = "Reason: domain; $mesg = "Reason: static; $mesg = "Reason: geogrid; $mesg = "Reason: ess (-e $wpsnl or -e The domain directory, $domain, does not exist" unless -e $ The static directory, $static, does not exist" unless -e $ I can't find the geogrid routine, $geogrid" Missing necessary namelist file(s),\n\n $wpsnlo); unless -e $ $wpsnl" unl

if ($mesg) { &emsprint(6,7,96,2,1,"WRF EMS Inspirational Message #$err - Help Me, Hel p You",$mesgs); &emsprint(0,19,256,1,2,$mesg); return 1; } $mesg = "Updating localization for $dom domain"; &emsprint(0,9,96,2,0,$mesg);

chdir $static; # We (like there's more than one of us?!) need to determine which namelist file # to use. Let's assume that it's the one that was modified most recently. # my %masternl; my %newnl; if (-e $wpsnl and -e $wpsnlo) { my my # # n # copy namelist.wps.orig to namelist.wps. Just because. # if ($snl->mtime > $snlo->mtime) { # namelist.wps is newer than namelist. wps.orig - use namelist.wps %masternl = &nltohash($wpsnlo); %newnl = &nltohash($wpsnl); # Now move the important fields over to the template (orig) hash # delete $masternl{GEOGRID}{$_} foreach keys %{$masternl{GEOGRID}}; @{$masternl{GEOGRID}{$_}} = @{$newnl{GEOGRID}{$_}} foreach keys %{$n ewnl{GEOGRID}}; delete $masternl{UNGRIB}{$_} foreach keys %{$masternl{UNGRIB}}; @{$masternl{UNGRIB}{$_}} = @{$newnl{UNGRIB}{$_}} foreach keys %{$new nl{UNGRIB}}; delete $masternl{METGRID}{$_} foreach keys %{$masternl{METGRID}}; @{$masternl{METGRID}{$_}} = @{$newnl{METGRID}{$_}} foreach keys %{$n ewnl{METGRID}}; @{$masternl{SHARE}{wrf_core}} = @{$newnl{SHARE}{wrf_core}} if @{$new nl{SHARE}{wrf_core}}; } elsif ($snl->mtime < $snlo->mtime) { %masternl = &nltohash($wpsnlo); } else { %masternl = &nltohash($wpsnl); } } elsif (-e $wpsnlo) { %masternl = &nltohash($wpsnlo); } else { %masternl = &nltohash($wpsnl); } my $core = ($masternl{SHARE}{wrf_core}[0] =~ /ARW/i) ? 'arw' : ($masternl{SH ARE}{wrf_core}[0] =~ /NMM/i) ? 'nmm' : ''; # Do some additional cleanup of the namelist # $masternl{SHARE}{max_dom}[0] = scalar @{$masternl{GEOGRID}{parent_id}}; for my $i (0 .. $masternl{SHARE}{max_dom}[0]-1) { $snl $snlo If the values = stat($wpsnl); = stat($wpsnlo); user edited the namelist.wps file most recently then take the from that file and add then to the namelist.wps.orig file, the

$masternl{SHARE}{start_date}[$i] = $masternl{SHARE}{start_date}[0]; $masternl{SHARE}{end_date}[$i] = $masternl{SHARE}{end_date}[0]; # Check the grid ratios if a nested domain # my $dom = $i+1; my $mesg; if ($i) { my $nr = $masternl{GEOGRID}{parent_grid_ratio}[$i]; $mesg = "The NMM only allows child:parent grid ratios of 3:1.\nDomai n $dom has ". "a ratio of $nr:1." if $core eq 'nmm' and $nr != 3; $mesg = "The ARW recommends a child:parent grid ratio of either 3:1 or 5:1.\nDomain $dom ". "has a ratio of $nr:1. Ok, you've been warned." if $core eq 'arw' and $nr != 3 and $nr != 5; &emsprint(3,6,76,3,1,"WRF EMS Inspirational Message #$err - Help Me, Help You",$mesg) if $mesg and $core eq 'nmm'; &emsprint(6,6,88,2,1,"WRF EMS Suggestion #$err - Help Me, Help You", $mesg) if $mesg and $core eq 'arw'; return 1 if $core eq 'nmm' and $mesg; my my my my $e_sn $e_we $n_sn $n_we = = = = $masternl{GEOGRID}{e_sn}[$i]; $masternl{GEOGRID}{e_we}[$i]; $e_sn; $e_we;

if ($core eq 'nmm') {$n_sn = $n_sn + 1 if $n_sn % 2 == 1;} my $uc = uc $core; $n_sn = $n_sn - 2 while ( (($n_sn-1)/$nr)/int(($n_sn-1)/$nr) > 1); $n_we = $n_we - 1 while ( (($n_we-1)/$nr)/int(($n_we-1)/$nr) > 1); if ($e_sn != $n_sn) { my $err = int rand(1000); $mesg = "The south-north grid dimension for domain $dom does not meet the strict ". "requirements clearly spelled out somewhere in the $uc U sers Guide.\nChanging ". "the south-north dimension from $e_sn to $n_sn. I really hope you don't mind."; &emsprint(6,6,86,2,1,"WRF EMS Inspirational Message #$err - Help Me, Help You",$mesg); $masternl{GEOGRID}{e_sn}[$i] = $n_sn; } if ($e_we != $n_we) { my $err = int rand(1000); $mesg = "The west-east grid dimension for domain $dom does not m eet the strict ". "requirements clearly spelled out somewhere in the $uc U sers Guide.\nChanging ". "the west-east dimension from $e_we to $n_we. I really h ope you don't mind."; &emsprint(6,6,86,2,1,"WRF EMS Inspirational Message #$err - Help Me, Help You",$mesg);

$masternl{GEOGRID}{e_we}[$i] = $n_we; } } } # Make sure there is only a single value in the ref_x & ref_y # @{$masternl{GEOGRID}{ref_y}} = (); $masternl{GEOGRID}{ref_y}[0] = $masternl{GEOGRID}{e_sn}[0]/2; @{$masternl{GEOGRID}{ref_x}} = (); $masternl{GEOGRID}{ref_x}[0] = $masternl{GEOGRID}{e_we}[0]/2; # Check to make sure that the necessary paths are specified correctly and t hen write # out the namelist again. # $masternl{SHARE}{opt_output_from_geogrid_path}[0] = "\'$static\'"; $masternl{GEOGRID}{geog_data_path}[0] = "\'$ENV{EMS}/data/geog\'"; $masternl{GEOGRID}{opt_geogrid_tbl_path}[0] = "\'$static\'"; # Modify domain Wizard stuff # my $dwdx; if ($core eq 'nmm') { my $dx = $masternl{GEOGRID}{dx}[0]*107.5251; my $dy = $masternl{GEOGRID}{dy}[0]*111.3206; $dwdx = sqrt($dx*$dx + $dy*$dy); } else { my $dx = $masternl{GEOGRID}{dx}[0]; my $dy = $masternl{GEOGRID}{dy}[0]; $dwdx = ($dx + $dy) * 0.5; } $masternl{DOMAIN_WIZARD}{dwiz_name}[0] = lc $dom; $masternl{DOMAIN_WIZARD}{dwiz_gridpt_dist_km}[0] = sprintf("%f",$dwdx); $masternl{DOMAIN_WIZARD}{dwiz_stand_lon}[0] = $masternl{GEOGRID}{ref_lon}[0] ; $masternl{DOMAIN_WIZARD}{dwiz_truelat1}[0] = $masternl{GEOGRID}{ref_lat}[0] ; $masternl{DOMAIN_WIZARD}{dwiz_truelat2}[0] = $masternl{GEOGRID}{ref_lat}[0] ; # Clean up the directory of previous localization files # &rm("$static/GEOGRID.TBL"); &rm($wpsnlo); opendir DIR => $static; &rm("$static/$_") foreach (grep /geo_/ => readdir DIR); closedir DIR; # Determine what GEOGRID table to use and make the appropriate link # my $table = $core eq 'nmm' ? "GEOGRID.TBL.NMM" : "GEOGRID.TBL.ARW"; $table = "$ENV{DATA_TBLS}/wps/$table"; symlink "$table" => "$static/GEOGRID.TBL"; # Print out namelist file # &hashtonl($wpsnl,"$EMSinstall{EMSDIR}/data/tables/wps/namelist.wps",%mastern l);

# Now run GEOGRID # my $logr = "$static/domain_geogrid.log"; if (system "$geogrid >& $logr") { &emsprint(0,1,24,0,1,' - Failed'); &emsprint(6,7,256,1,1,'Error running GEOGRID. See domain_geogrid.log for more details'); return 1; } &emsprint(0,1,24,0,1,' - Success'); $mesg = "You must manually run \"ems_clean --level 4\" from the $domain doma in before runing a simulation."; &emsprint(6,9,96,1,1,$mesg); opendir DOMAIN => $domain; foreach (readdir(DOMAIN)) { &rm("$domain/$_") unless ($_ eq "." or $_ eq ".." or /^static$|^conf$/); } closedir DOMAIN; # Create a .arw or .nmm file in the static directory # &rm("$static/.nmm"); &rm("$static/.arw"); system "touch $static/.$core"; # My work is done here. Clean up static directory # &rm("$static/GEOGRID.TBL"); return; } # End of &localize sub hashtonl { #--------------------------------------------------------------------------------# This routine takes the name of a namelist file and a hash of namelist section s # and variables (a hash of a hash) and writes the information to the namelist # file. Basically, the reverse of nltohash. #--------------------------------------------------------------------------------# my ($nl, $template, %hash) = @_; # Save off the original namelist file should things go horribly wrong. # system "mv $nl $nl\.orig" if -e $nl and ! -e "$nl\.orig"; my %nlorder = &nlorder($template); # Open namelist file for writing # open NL => ">$nl" or die "\n EMS BUMMER: Could not open namelist file ($n l)\n"; foreach my $sect (@{$nlorder{order}}) { print NL "&",lc $sect,"\n";

foreach my $field (@{$nlorder{$sect}}) { next unless defined @{$hash{uc $sect}{$field}} and @{$hash{uc $sect} {$field}}; my $valu = join ", " => @{$hash{uc $sect}{$field}}; my $line = sprintf (" %-26s = %s",lc $field,$valu); print NL "$line\n"; } print NL "/\n\n"; } close NL; return; } sub nlorder { #--------------------------------------------------------------------------------# This routine reads the contents of a default namelist to get the desired # order for the fields printed to the namelists in the users runs. The reason # for this routine is that since the primary namelist list is help in a hash, # it prints in random order and thus can be confusing to a reader. This # could be built into the nltohash routine but this appears easier. #--------------------------------------------------------------------------------# my %hash; my $sect; # namelist is the only argument passed into routine # my $nl = shift; open NL, $nl or die "\n EMS BUMMER: Could not open namelist file ($nl)\n" ; while (<NL>) { chomp; next if /^#|^$/; undef $sect if $sect and /^\s*(\/)/; if ($sect) { my ($var, $value) = split(/\s*=\s*/, $_, 2); # Eliminate training comma. Also do some clean up string by eliminat ing multiple # white spaces between values. # $var =~ s/ //g; $var = lc $var; push @{$hash{$sect}} => $var if defined $value; } if (s/^\s*(&)//g) { $sect = lc $_; push @{$hash{order}} => $sect; } } close NL; return %hash; }

sub nltohash { #--------------------------------------------------------------------------------# This routine reads a WRF namelist and writes it to a hash. Each hash contains a # list of nl variables with a list of values. So, a hash of lists of lists. Got it. # Returns the hash. #--------------------------------------------------------------------------------# my $sect; my $tvr; my %hash; # namelist is the only argument passed into routine # my $nl = shift; open NL, $nl or die "\n EMS BUMMER: Could not open namelist file ($nl)\n" ; while (<NL>) { chomp; next if /^#|^$/; undef $sect if $sect and /^\s*(\/)/; if ($sect) { my ($var, $value) = split(/\s*=\s*/, $_, 2); # Eliminate training comma. Also do some clean up string by eliminat ing multiple # white spaces between values. # $var =~ s/ //g; $var = lc $var; $value =~ s/(,\s*)$//g; if (defined $value) { # clean up entries in the configuration file by removing # training commas and white spaces and also substituting commas # for (semi-) colons. # $tvr = $var; $value =~ s/ //g; my @list = split /,/ => $value; @{$hash{uc $sect}{lc $var}} = @list; } else { # A continuation of the previous value $var =~ s/ //g; $var =~ s/(,\s*)$//g; my @list = split /,/ => $var; push @{$hash{uc $sect}{lc $tvr}}, @list; } } $sect = uc $_ if s/^\s*(&)//g; } close NL; return %hash; }

sub subset { #--------------------------------------------------------------------------------# my @files = @_; return @files unless $EMSinstall{MATCH} or $EMSinstall{NOMATCH}; my @subset=(); foreach my $file (@files) { my $pfile = &popit($file); my $match = $EMSinstall{MATCH} ? 0 : 1; foreach my $str (split /,|;/ => $EMSinstall{MATCH}) { $match = 1 if $pfile =~ /$str/i; } next unless $match; $match = 0; foreach my $str (split /,|;/ => $EMSinstall{NOMATCH}) { $match = 1 if $pfile =~ /$str/i; } next if $match; push @subset => $file; } return @subset; } sub get_iver { #--------------------------------------------------------------------------------# Routine reads the contents of the $EMS/strc/.release file and returns # the version number and release date information. #--------------------------------------------------------------------------------# my $mesg; my $rv; my $rd; my $ems = shift; my $rf = $ems ? "$ems/strc/.release" : "$ENV{EMS}/strc/.release"; return '00.00.00.00' unless -e $rf; open VF => $rf; my @lines = <VF>; close VF; my $rv = join ", " => @lines; ch omp $rv; $rv =~ s/ //g; $rv =~ s/WRFEMS//g; # # # my if Do some slight reformatting for the trailing "beta" or "dev" designation. @list = split /\./ => $rv; ($list[$#list] =~ /(\d+)(\D)/) { $list[$#list] = $1; if ($2 =~ /^e/i) { $list[$#list+1] = 'dev';

} elsif ($2 =~ /^b/i) { $list[$#list+1] = 'beta'; } $rv = join ".", @list; } # split the string at the "RD" to get the release version and date # ($rv, $rd) = split /RD/i => $rv; return $rv; } sub ems_inspire { #--------------------------------------------------------------------------------# An inspirational message to the user in the event of a screw-up #--------------------------------------------------------------------------------# my $mesg = shift; return unless $mesg; my $err = int rand(1000); my $tab = ' '; my $im = &ems_messages; my $lm = length $im;

my $c = '"'; my $i = rindex $im,$c; my $q = substr $im, 0, $i+1; my $a = substr $im, $i+1; $a =~ s/^ +//g; $a =~ s/ +$//g; my $ca = 80 - length $a; $ENV{VERBOSE} = 1; &emsprint(6,6,88,2,1,"WRF EMS Inspirational Message #$err - Help Me, Help Y ou"); &emsprint(0,9,82,1,2,$mesg); &emsprint(0,9,82,1,1,$q); &emsprint(0,$ca,82,0,1,$a); return; } sub getprocs { #--------------------------------------------------------------------------------# Get the user's input on the system processor information #--------------------------------------------------------------------------------# my $mesg; my $machine = `hostname -s`; chomp $machine; my $nprocs = $EMSinstall{NCORES} * $EMSinstall{NCPUS}; $mesg = "The EMS installation routine has determined that there are $EMSinst all{NCPUS} ".

"physical CPUs on $machine with $EMSinstall{NCORES} cores per CPU fo r a grand ". "total of $nprocs processors. If these values are not correct then this is ". "your opportunity to do something about it.\n\n". "So, before before we continue you need to verify the correct number of physical ". "processors and cores per processor on $machine.\n\n". " $EMSinstall{NCPUS} PHYSICS CPUs - Those that you would see if yo u opened up the computer case\n\n". " $EMSinstall{NCORES} CORES per CPU - Just that and not the total n umber of available processors\n\n". "Note that if you plan on running the EMS on a cluster then that con figuration is done ". "manually after the basic installation. All I want is the informatio n for $machine."; &emsprint(1,4,92,2,1,"Local CPU information for $machine",$mesg); $mesg = "Are the values above correct for this machine? [Yes] "; &emsprint(0,7,96,2,0,$mesg); my $ans = <>; chomp $ans; chomp $ans; $ans = $ans ? $ans : "Yes"; my $ga = $ans =~ /^Y/i; while (!$ga) { $mesg = "How many PHYSICAL CPUs are there on $machine? [$EMSinstall{NCPU S}] "; &emsprint(0,12,96,1,0,$mesg); my $ans = <>; chomp $ans; $EMSinstall{NCPUS} = $ans ? $ans : $EMSinstall{NCPUS}; $ga = 1 if ($ans ne '0' and $EMSinstall{NCPUS}); $mesg = "How many CORES per CPU are there on $machine? [$EMSinstall{NCOR ES}] "; &emsprint(0,12,96,1,0,$mesg); my $ans = <>; chomp $ans; $EMSinstall{NCORES} = $ans ? $ans : $EMSinstall{NCORES}; $ga = 1 if ($ans ne '0' and $EMSinstall{NCPUS}); my $nprocs = $EMSinstall{NCORES} * $EMSinstall{NCPUS}; $mesg = "So, you are telling me that there are $EMSinstall{NCPUS} CPUs * ". "$EMSinstall{NCORES} cores for a total of $nprocs processors on $machine.\n\n". "Are you happy with these values? [Yes] "; &emsprint(0,7,96,1,0,$mesg); my $ans = <>; chomp $ans; chomp $ans; $ans = $ans ? $ans : "Yes"; $ga = $ans =~ /^Y/i; }

my $nprocs = $EMSinstall{NCORES} * $EMSinstall{NCPUS}; $mesg = "There are $EMSinstall{NCPUS} CPUs * $EMSinstall{NCORES} cores for a total ". "of $nprocs processors on $machine.\n\nYou can change these values i n ". "$EMSinstall{EMSDIR}/EMS.cshrc if necessary."; &emsprint(1,4,96,2,2,$mesg); return; } sub ems_messages { #--------------------------------------------------------------------------------# An inspirational message when needed and it is always needed #--------------------------------------------------------------------------------# my @inspired; @inspired = ("\"What we got here is failure to communicate\" - Cool Hand Luk e", "\"A man who carries a cat by the tail learns something he can learn in no other way\" - Mark Twain", "\"A person who won't read has no advantage over one who can't read\" - Mark Twain", "\"A person with a new idea is a crank until the idea succeeds\ " - Mark Twain", "\"Action speaks louder than words but not nearly as often\" Mark Twain", "\"All generalizations are false, including this one\" - Mark T wain", "\"All right, then, I'll go to hell.\" - Mark Twain", "\"All you need is ignorance and confidence and the success is sure\" - Mark Twain", "\"Buy land, they're not making it anymore\" - Mark Twain", "\"Climate is what we expect, weather is what we get.\" - Mark Twain", "\"Clothes make the man. Naked people have little or no influen ce on society.\" - Mark Twain", "\"Do the right thing. It will gratify some people and astonish the rest.\" - Mark Twain", "\"Don't tell fish stories where the people know you; but parti cularly, don't tell them where they know the fish.\" - Mark Twain", "\"Facts are stubborn, but statistics are more pliable.\" - Mar k Twain", "\"Get your facts first, then you can distort them as you pleas e.\" - Mark Twain", "\"Go to Heaven for the climate, Hell for the company.\" - Mark Twain", "\"Honesty is the best policy - when there is money in it.\" Mark Twain", "\"We have the best government that money can buy.\" - Mark Twa in", "\"What would men be without women? Scarce, sir, mighty scarce. \" - Mark Twain", "\"When you fish for love, bait with your heart, not your brain .\" - Mark Twain",

"\"Think Globally, Model Locally\" - WRF EMS", "\"The trouble ain't that there is too many fools, but that the lightning ain't distributed right.\" - Mark Twain", "\"The very ink with which history is written is merely fluid p rejudice.\" - Mark Twain", "\"Thunder is good, thunder is impressive; but it is lightning that does the work.\" - Mark Twain", "\"The fear of death follows from the fear of life. A man who l ives fully is prepared to die at any time.\" - Mark Twain", "\"The main difference between a cat and a lie is that a cat on ly has nine lives.\" - Mark Twain", "\"The more things are forbidden, the more popular they become. \" - Mark Twain", "\"The reports of my death have been greatly exaggerated.\" - M ark Twain", "\"Reader, suppose you were an idiot. And suppose you were a me mber of Congress. But I repeat myself.\" - Mark Twain", "\"Sometimes too much to drink is barely enough.\" - Mark Twain ", "\"The best way to cheer yourself up is to try to cheer somebod y else up.\" - Mark Twain", "\"If you tell the truth, you don't have to remember anything.\ " - Mark Twain", "\"It is better to deserve honors and not have them than to hav e them and not deserve them.\" - Mark Twain", "\"It is better to keep your mouth closed and let people think you are a fool than to open it and remove all doubt.\" - Mark Twain", "\"It's not the size of the dog in the fight, it's the size of the fight in the dog.\" - Mark Twain", "\"I didn't attend the funeral, but I sent a nice letter saying I approved of it.\" - Mark Twain", "\"I have never let my schooling interfere with my education.\" - Mark Twain", "\"Habit is habit and not to be flung out of the window by any man, but coaxed downstairs a step at a time.\" - Mark Twain", "\"You just pick up a chord, go twang, and you're got music\" Sid Vicious"); my $i = int rand($#inspired); return $inspired[$i]; } sub sdsets { my %hash; my $mesg; my $key = shift; for ($key) { s/wrf.geog_//g; s/\.tbz|\.tgz//g; } switch ($key) { case /modislanduse/ {return "MODIS Land Use - 30\" (~1km), 20-category M ODIS land-cover classification of the IGBP (NOAH LSM only)";} case /orogwd/ {return "Gravity Wave Drag by Orography data sets for use with the ARW core";}

case /tsoil/ ;}

{return "Adjusted Mean Annual Soil Temperatures 1 degree"

case /topo/ {return "USGS Topography - 30\" (~1km), 2' (~3.7km), 5' ( ~9.2km) and 10' (~18.5km) grid average elevation";} case /soiltop/ {return "Top Layer Soil Type - 30\" (~1km), 2' (~3.7km), 5' (~9.2km) and 10' (~18.5km) 16-category dominant type (silt, sand, clay, bedro ck)";} case /soilbot/ {return "Bottom Layer Soil Type - 30\" (~1km), 2' (~3.7km ), 5' (~9.2km) and 10' (~18.5km) 16-category dominant type (silt, sand, clay, be drock)";} case /landuse/ {return "USGS Land Use - 30\" (~1km), 2' (~3.7km), 5' (~9 .2km) and 10' (~18.5km) 24-category dominant type (wetland, water, forest)";} case /greenfrac/ {return "Annual Greenness Fraction - 0.15 degree (~16km ; max, min)";} case /albedo/ {return "Climatological monthly and maximum snow albedo 0.15 degrees";} } return "Unknown Data set: $key";; } sub didyouknow { #--------------------------------------------------------------------------------# Information to be printed out at various times during the downloading and # installation process. #--------------------------------------------------------------------------------# return unless @{$EMSinstall{DYKS}}; my @headers = ("\"DID YOU KNOW?\"", "\"DID YOU NEED TO KNOW?\"", "\"DO YOU CARE?\""); my $mesg = shift @{$EMSinstall{DYKS}}; my $head = $headers[int rand($#headers)]; &emsprint(0,14,108,1,1,$head,$mesg); return; } sub dykinit { #--------------------------------------------------------------------------------# Initialize DYK statements #--------------------------------------------------------------------------------# my @messages; my $mesg; $mesg = "The STRC WRF EMS is an end-to-end forecasting system, from inge sting the data used for ". "model initialization to post-processing and exporting the forec asts the their final destination."; push @messages => $mesg; $mesg = "There are a variety of tools available to EMS users, includi ng:\n\n".

" ems_clean ified\n". " nformation.\n\n". " ems_guide ers guide, \n". " " gribnav prints out\n". " and center\n". " ing.\n\n". " netcheck lems when \n". " ems.\n\n". " sysinfo ding the number\n". " y, and a whole\n". " about.\n\n". " runinfo r a selected\n". " main directory\n". " e stimulated by\n". " \n". " grib2cdf les from GRIB \n". " push @messages => $mesg;

- Restores run-time directories to a user-spec state. Run \"% ems_clean --help\" for more i - Is the most up-to-date version of the EMS us which still isn't saying much.\n\n". - Reads the GDS block of GRIB 1 or 2 files and the navigation information including corner points, pole point, grid dimensions and spac - A tool for finding potential networking prob executing the EMS on a cluster of Linux syst - Provides information about your system inclu of CPUs, CPU speed, amount of physical memor lot more stuff that you never cared to know - Provides details of the run configuration fo model domain. Simply run \"runinfo\" in a do and allow your state of semi-consciousness b the shmorgishborg of valuable information.\n - Creates standard netCDF and companion cdl fi version 1 and 2 files - Enjoy!";

$mesg = "That the WRF EMS includes a modified version of the Domain Wiza rd ". "developed by Earth System Research Laboratory (ESRL)? This tool ". "greatly simplifies the task of setting up the computational dom ain ". "for your simulations.\n\n". "Simply run from the command line:\n\n". " % dwiz"; push @messages => $mesg; $mesg = "That the WRF EMS provides benchmark simulations for both the NM M and ARW cores? This ".

"utility will allow you to compare the performance of each model on your workstation ". "to that on other platforms. In addition running a benchmark wil l verify that the EMS ". "is working on your system.\n\n". "To run a benchmark case after the install:\n\n". " 1. cd \$EMSinstall{EMSDIR}/util/benchmark \n". " 2. Read the benchmark.README file\n". " 3. cd to either core directory (arw or nmm)\n". " 4. Run the benchmark case as per the guidance\n". " 5. Send the results of your benchmark simulation to the SOO \ STRC"; push @messages => $mesg; $mesg = "The WRF EMS contains an advanced version of the operational NMM core run at NCEP."; push @messages => $mesg; $mesg = "The WRF EMS includes the much talked about (just by me) option to the $EMSinstall{EXE} routine ". "that allows you to automatically (via cron) download and instal l patches and updates while ". "you sleep. It will even send you email letting you know that th e system was updated."; push @messages => $mesg; $mesg = "The WRF EMS includes a variety of utility routines that may be used to enhance your ". "modeling experience. I know you are saying \"How is this possib le!?\", but it's true.\n\n". "Here is a summary of the file in the wrfems/util/bin directory: \n\n". " cnvgrib - Utility (GRIB 1 <-> GRIB 2)\n". " copygb - Utility ection/navigation (GRIB 1 only)\n". " g1print - Utility or the creation of Vtables\n". " g2print - Utility or the creation of Vtables\n". " ncdump - Utility matted files\n". " ncview - Display es - Fun for all ages\n". " rdwrfin - Utility ediate formatted files\n". " rdwrfnc - Utility formatted files\n". " wgrib - Utility ". " wgrib2 - Utility rmatted files\n". push @messages => $mesg; to convert between GRIB Version 1 and 2 to interpolate to a different grid proj to dump information from GRIB 1 files f to dump information from GRIB 2 files f to dump out information from netCDF for tool for the the contents of netCDF fil to dump out information from WRF interm to dump out information from WRF netCDF to interrogate GRIB 1 formatted files\n to interrogate and manipulate GRIB 2 fo

return @messages; } sub int_handle { #--------------------------------------------------------------------------------# Override the default behavior when sending an interrup signal. #--------------------------------------------------------------------------------# my $mesg = "Ouch! - Aren't we a bit sensitive?! Let's do this again sometime very soon!"; &emsprint(0,4,96,3,3,$mesg); exit; } sub envcheck { #--------------------------------------------------------------------------------# Check to make sure the environment variables are set correctly. #--------------------------------------------------------------------------------# use Text::Wrap; my $mesg; my $ind = " ";

$mesg = "It appears that the EMS environment is not defined. This can be accomplished by ". "setting an EMS environment variable that defines the top levels of the WRF EMS ". "distribution in your login shell OR setting the EMS variable at the top of this ". "routine. It's your choice. Don't make me print this message aga in." unless defined $ENV{EMS}; $mesg = "It appears that the EMS environment is not correctly defined($E NV{EMS}). This can be accomplished by ". "setting an EMS environment variable that defines the top levels of the WRF EMS ". "distribution in your login shell OR setting the EMS variable at the top of this ". "routine. It's your choice. Don't make me print this message aga in." unless -e "$ENV{EMS}/strc/.release"; if ($mesg) { print wrap($ind,$ind,"\n\nEMS environment variable is not correctly defined!\n\n"); print wrap($ind,$ind,"$mesg\n\n"); return 1; } return (defined $ENV{EMS_HOME} and $ENV{EMS_HOME} eq $ENV{EMS}) ? 0 : 1; }

You might also like