| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Simulation::Automate::Remote; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 2 |  |  | 2 |  | 11 | use vars qw( $VERSION ); | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 113 |  | 
| 4 |  |  |  |  |  |  | $VERSION = "1.0.1"; | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | ################################################################################# | 
| 7 |  |  |  |  |  |  | #                                                                              	# | 
| 8 |  |  |  |  |  |  | #  Copyright (C) 2003 Wim Vanderbauwhede. All rights reserved.                  # | 
| 9 |  |  |  |  |  |  | #  This program is free software; you can redistribute it and/or modify it      # | 
| 10 |  |  |  |  |  |  | #  under the same terms as Perl itself.                                         # | 
| 11 |  |  |  |  |  |  | #                                                                              	# | 
| 12 |  |  |  |  |  |  | ################################################################################# | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | #headers | 
| 15 |  |  |  |  |  |  | # | 
| 16 |  |  |  |  |  |  | #Support module for remote runs | 
| 17 |  |  |  |  |  |  | #This implementation requires: | 
| 18 |  |  |  |  |  |  | #-ssh access to remote host | 
| 19 |  |  |  |  |  |  | #-scp access to remote host | 
| 20 |  |  |  |  |  |  | #-rsync server on the local host | 
| 21 |  |  |  |  |  |  | #-or,alternatively, an NFS mounted home directory | 
| 22 |  |  |  |  |  |  | #-as such, it'll probably only work on Linux and similar systems | 
| 23 |  |  |  |  |  |  | # | 
| 24 |  |  |  |  |  |  | #$Id$ | 
| 25 |  |  |  |  |  |  | # | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | #usage: | 
| 28 |  |  |  |  |  |  | #sub synsim { | 
| 29 |  |  |  |  |  |  | #if(&check_for_remote_host==1){ | 
| 30 |  |  |  |  |  |  | #&run_on_remote_host() | 
| 31 |  |  |  |  |  |  | #} else { | 
| 32 |  |  |  |  |  |  | #&run_local(); # new name for sub synsim | 
| 33 |  |  |  |  |  |  | #} | 
| 34 |  |  |  |  |  |  | #} | 
| 35 |  |  |  |  |  |  |  | 
| 36 | 2 |  |  | 2 |  | 8 | use strict; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 52 |  | 
| 37 | 2 |  |  | 2 |  | 8 | use Cwd; | 
|  | 2 |  |  |  |  | 2 |  | 
|  | 2 |  |  |  |  | 178 |  | 
| 38 | 2 |  |  | 2 |  | 12 | use Exporter; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 1990 |  | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | @Simulation::Automate::Remote::ISA = qw(Exporter); | 
| 41 |  |  |  |  |  |  | @Simulation::Automate::Remote::EXPORT = qw( | 
| 42 |  |  |  |  |  |  | &check_for_remote_host | 
| 43 |  |  |  |  |  |  | &run_on_remote_host | 
| 44 |  |  |  |  |  |  | ); | 
| 45 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 46 |  |  |  |  |  |  | sub check_for_remote_host { | 
| 47 | 1 | 50 | 33 | 1 | 0 | 88 | (!@ARGV || $ARGV[@ARGV-1]=~/^\-/) && return 0; # not a host name | 
| 48 | 0 |  |  |  |  |  | my $arg=@ARGV[@ARGV-1]; | 
| 49 |  |  |  |  |  |  |  | 
| 50 | 0 |  |  |  |  |  | my $remotehost=''; | 
| 51 | 0 | 0 | 0 |  |  |  | if(($arg!~/\.data/)&&($arg ne '-h')) { | 
| 52 | 0 |  |  |  |  |  | $remotehost=pop @ARGV; | 
| 53 | 0 |  |  |  |  |  | chomp(my $reply=`ssh $remotehost hostname -s 2>&1`); | 
| 54 | 0 |  |  |  |  |  | my $remotehostshort=$remotehost; | 
| 55 | 0 |  |  |  |  |  | $remotehostshort=~s/\..*$//; | 
| 56 | 0 | 0 |  |  |  |  | if($reply ne $remotehostshort){ | 
| 57 | 0 |  |  |  |  |  | $remotehost.='FAIL'; | 
| 58 |  |  |  |  |  |  | } | 
| 59 |  |  |  |  |  |  | } | 
| 60 | 0 |  |  |  |  |  | return $remotehost; #0: local; 1: remote OK; 2: remote FAIL | 
| 61 |  |  |  |  |  |  | } #END of check_for_remote_host | 
| 62 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 63 |  |  |  |  |  |  | sub run_on_remote_host { | 
| 64 | 0 |  |  | 0 | 0 |  | my $remotehost=shift; | 
| 65 | 0 | 0 |  |  |  |  | if( $remotehost=~s/FAIL//) { | 
| 66 | 0 |  |  |  |  |  | die "Could not establish SSH connection to $remotehost\n"; | 
| 67 |  |  |  |  |  |  | } | 
| 68 | 0 |  |  |  |  |  | my $datafile=@ARGV[@ARGV-1]; | 
| 69 | 0 |  |  |  |  |  | my $user=$ENV{USER}; | 
| 70 | 0 |  |  |  |  |  | chomp(my $localhost= `hostname -s 2>&1`); | 
| 71 |  |  |  |  |  |  |  | 
| 72 | 0 |  |  |  |  |  | my $localsynsimpath=cwd(); | 
| 73 | 0 |  |  |  |  |  | my $rundir=$localsynsimpath; | 
| 74 | 0 |  |  |  |  |  | my $homepath=$localsynsimpath; | 
| 75 | 0 |  |  |  |  |  | $homepath=~s/$user.*$//; | 
| 76 | 0 |  |  |  |  |  | $homepath.=$user; | 
| 77 | 0 |  |  |  |  |  | $rundir=~s/^.*\///; | 
| 78 | 0 |  |  |  |  |  | $localsynsimpath=~s/\w+$//; #dangerous! | 
| 79 | 0 |  |  |  |  |  | $localsynsimpath=~s/.*$user\///; #dangerous! | 
| 80 | 0 |  |  |  |  |  | $localsynsimpath=~s/\/$//; | 
| 81 |  |  |  |  |  |  |  | 
| 82 | 0 |  |  |  |  |  | my $remotesynsimpath=$localsynsimpath; | 
| 83 |  |  |  |  |  |  |  | 
| 84 | 0 |  |  |  |  |  | chomp(my $simdir=`egrep '^SIMTYPE' $datafile`); | 
| 85 | 0 |  |  |  |  |  | $simdir=~s/SIMTYPE\s+:\s+//; | 
| 86 | 0 |  |  |  |  |  | $simdir.='-'.$datafile; | 
| 87 | 0 |  |  |  |  |  | $simdir=~s/\.data$//; | 
| 88 |  |  |  |  |  |  |  | 
| 89 | 0 |  |  |  |  |  | my %simdata=( | 
| 90 |  |  |  |  |  |  | '_DATAFILE'=>$datafile, | 
| 91 |  |  |  |  |  |  | '_USER'=>$user, | 
| 92 |  |  |  |  |  |  | '_LOCALHOST'=>$localhost, | 
| 93 |  |  |  |  |  |  | '_RUNDIR'=>$rundir, | 
| 94 |  |  |  |  |  |  | '_HOMEPATH'=>$homepath, | 
| 95 |  |  |  |  |  |  | '_LOCALPATH'=>$localsynsimpath, | 
| 96 |  |  |  |  |  |  | '_REMOTEPATH'=>$remotesynsimpath, | 
| 97 |  |  |  |  |  |  | ); | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | #to run SynSim on a remote machine: | 
| 100 | 0 |  |  |  |  |  | my $templfilename="TEMPLATES/synsim_remote.templ"; | 
| 101 | 0 | 0 |  |  |  |  | if(not -e $templfilename) { | 
| 102 | 0 |  |  |  |  |  | &create_template($templfilename); | 
| 103 |  |  |  |  |  |  | } | 
| 104 | 0 |  |  |  |  |  | my $scriptname="synsim_remote.pl"; | 
| 105 | 0 |  |  |  |  |  | open (PL,">$scriptname"); | 
| 106 | 0 | 0 |  |  |  |  | open (TEMPL, "<$templfilename")||die "Can't open $templfilename\n"; | 
| 107 | 0 |  |  |  |  |  | while (my $line = ) { | 
| 108 |  |  |  |  |  |  |  | 
| 109 | 0 |  |  |  |  |  | foreach my $key (keys %simdata) { | 
| 110 | 0 | 0 |  |  |  |  | ($key!~/^_/) && next; | 
| 111 | 0 |  |  |  |  |  | $line =~ s/$key(?!\w)/$simdata{$key}/g; | 
| 112 |  |  |  |  |  |  | } # foreach | 
| 113 | 0 |  |  |  |  |  | print PL $line; | 
| 114 |  |  |  |  |  |  | } # while | 
| 115 | 0 |  |  |  |  |  | close TEMPL; | 
| 116 | 0 |  |  |  |  |  | close PL; | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | # In case we use NFS, we should not scp or rsync. | 
| 119 |  |  |  |  |  |  | #Simple check: create a file with the name of the localhost, and check for its existence over ssh | 
| 120 | 0 |  |  |  |  |  | my $nfstest="$homepath/$localsynsimpath/$rundir/$localhost"; | 
| 121 | 0 |  |  |  |  |  | system("touch $nfstest"); | 
| 122 |  |  |  |  |  |  | #print STDERR qq(ssh $remotehost  perl -e \'if ( -e "$nfstest" ){print "0"}else{print "1"}\');die; | 
| 123 | 0 |  |  |  |  |  | my $nonfs=`ssh $remotehost  "perl -e 'if ( -e qq($nfstest) ){print 0}else{print 1}'"`; | 
| 124 | 0 | 0 |  |  |  |  | if($nonfs) { | 
| 125 |  |  |  |  |  |  | #first time, or at start of run | 
| 126 |  |  |  |  |  |  | #actually, the best way is to create synsim_remote.pl on the fly | 
| 127 | 0 |  |  |  |  |  | system("scp $scriptname $remotehost:$scriptname"); | 
| 128 |  |  |  |  |  |  | #clean up; | 
| 129 | 0 |  |  |  |  |  | unlink $scriptname; | 
| 130 |  |  |  |  |  |  | #at start of synsim run | 
| 131 | 0 |  |  |  |  |  | system("ssh $remotehost  perl $scriptname"); | 
| 132 |  |  |  |  |  |  | #after synsim run, collect the data | 
| 133 |  |  |  |  |  |  | #system("rsync -uva ${remotehost}::home/$user/$remotesynsimpath/$rundir/$simdir ."); | 
| 134 | 0 |  |  |  |  |  | system("scp -C -r ${remotehost}:/local/home/$user/$remotesynsimpath/$rundir/$simdir ."); | 
| 135 |  |  |  |  |  |  | } else { | 
| 136 |  |  |  |  |  |  | # In case of NFS homedir, it's simpler: | 
| 137 | 0 |  |  |  |  |  | system("ssh $remotehost 'cd $homepath/$localsynsimpath/$rundir && ./synsim -p -f $datafile'"); | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  | } # END of run_on_remote_host | 
| 141 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 142 |  |  |  |  |  |  | sub create_template { | 
| 143 | 0 |  |  | 0 | 0 |  | my $templfilename=shift; | 
| 144 | 0 |  |  |  |  |  | open(TEMPL,">$templfilename"); | 
| 145 | 0 |  |  |  |  |  | print TEMPL <<'ENDTEMPL'; | 
| 146 |  |  |  |  |  |  | #!/usr/bin/perl -w | 
| 147 |  |  |  |  |  |  | use strict; | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  | #to run SynSim on a remote machine: | 
| 150 |  |  |  |  |  |  | #1. Needs a remote directory structure: | 
| 151 |  |  |  |  |  |  | #-all relative to $homepath | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | my $datafile='_DATAFILE'; | 
| 154 |  |  |  |  |  |  | my $user='_USER'; | 
| 155 |  |  |  |  |  |  | my $localhost='_LOCALHOST'; | 
| 156 |  |  |  |  |  |  | my $rundir='_RUNDIR'; | 
| 157 |  |  |  |  |  |  | my $localsynsimpath='_LOCALPATH'; | 
| 158 |  |  |  |  |  |  | my $remotesynsimpath='_REMOTEPATH'; | 
| 159 |  |  |  |  |  |  | my $homepath='_HOMEPATH'; | 
| 160 |  |  |  |  |  |  | $remotesynsimpath=~s/^\///; | 
| 161 |  |  |  |  |  |  | $remotesynsimpath=~s/\/$//; | 
| 162 |  |  |  |  |  |  | my @pathparts=split('/',$remotesynsimpath); | 
| 163 |  |  |  |  |  |  | $remotesynsimpath=''; | 
| 164 |  |  |  |  |  |  | chdir "$homepath"; | 
| 165 |  |  |  |  |  |  | foreach my $part (@pathparts){ | 
| 166 |  |  |  |  |  |  | $remotesynsimpath.="$part/"; | 
| 167 |  |  |  |  |  |  | if (not -d "$remotesynsimpath"){mkdir "$remotesynsimpath"}; | 
| 168 |  |  |  |  |  |  | } | 
| 169 |  |  |  |  |  |  | chdir "$remotesynsimpath"; | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  | #Beware! | 
| 172 |  |  |  |  |  |  | #This requires an rsync server with a module "home" on the local host; | 
| 173 |  |  |  |  |  |  | #${localhost}::home/$user must correspond to $homepath! | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | system("rsync -uva  ${localhost}::home/$user/$localsynsimpath/Simulation ."); | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | if (not -d "$rundir"){mkdir "$rundir" or die $!}; | 
| 178 |  |  |  |  |  |  | chdir "$rundir"; | 
| 179 |  |  |  |  |  |  | #system("rsync -uva  ${localhost}::home/$user/$localsynsimpath/$rundir/SOURCES ."); | 
| 180 |  |  |  |  |  |  | #system("rsync -uva  ${localhost}::home/$user/$localsynsimpath/$rundir/TEMPLATES ."); | 
| 181 |  |  |  |  |  |  | #system("rsync -uva  ${localhost}::home/$user/$localsynsimpath/$rundir/synsim ."); | 
| 182 |  |  |  |  |  |  | #system("rsync -uva  ${localhost}::home/$user/$localsynsimpath/$rundir/$datafile ."); | 
| 183 |  |  |  |  |  |  | system('scp -r -C ${localhost}:$homepath/$user/$localsynsimpath/$rundir/SOURCES ."); | 
| 184 |  |  |  |  |  |  | system('scp -r -C ${localhost}:$homepath/$user/$localsynsimpath/$rundir/TEMPLATES ."); | 
| 185 |  |  |  |  |  |  | system('scp -r -C ${localhost}:$homepath/$user/$localsynsimpath/$rundir/synsim ."); | 
| 186 |  |  |  |  |  |  | system('scp -r -C ${localhost}:$homepath/$user/$localsynsimpath/$rundir/$datafile ."); | 
| 187 |  |  |  |  |  |  | #now run synsim | 
| 188 |  |  |  |  |  |  | system("./synsim -v -p -f $datafile"); | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | #to get the results back, we'll scp from the other side | 
| 191 |  |  |  |  |  |  |  | 
| 192 |  |  |  |  |  |  | ENDTEMPL | 
| 193 |  |  |  |  |  |  | } | 
| 194 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 195 |  |  |  |  |  |  | 1; |