Salome HOME
Merge remote-tracking branch 'origin/vsr/fix_single_study_pb' into pre/fix_single_study
[modules/kernel.git] / bin / appliskel / runSalomeScript
1 #!/usr/bin/env python
2 #  -*- coding: utf-8 -*-
3 # Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
4 #
5 # Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
6 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 #
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21 #
22 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #
24
25 import os,sys,optparse
26 import socket,shutil
27 import re
28
29 usage="""
30         Connect to a SALOME session (local or remote) and execute a Python script with data files in argument (optional)
31
32         Usage: %prog [ options ] script
33
34           script           : The Python script to execute in the SALOME session
35
36         SALOME SESSION
37         --------------
38         If PORT and MACHINE are not given, try to connect to the last active session on the local machine
39         If PORT and MACHINE are given, try to connect to the remote session associated with PORT on MACHINE
40         If MACHINE is not given, try to connect to the session associated to PORT on the local machine
41         If PORT is not given, try to connect to the remote session associated to port 2810 on MACHINE
42
43         If MACHINE isn't localhost or hostname, USER is needed
44
45         If Salome isn't installed on the local machine, use APPLI_DIST to execute a distant session
46
47
48         INPUTS AND OUPUTS
49         -----------------
50         script is needed in all case
51         INPUT and OUTPUT are used only when Salome isn't on local machine. It defines a list of script (full path, blank separated)
52         Actions done with these two lists are :
53         - adjustment of path in a temporary script file
54         - copy of the input files and script file on the distant machine
55
56 """
57
58 appli_local=os.path.realpath(os.path.dirname(__file__))
59
60 def get_hostname():
61   return socket.gethostname().split('.')[0]
62
63 def vararg_callback(option, opt_str, value, parser):
64   """optparse callback for variable length arguments"""
65   assert value is None
66
67   done = 0
68   value = []
69   rargs = parser.rargs
70   while rargs:
71     arg = rargs[0]
72
73     # Stop if we hit an arg like "--foo", "-a", "-fx", "--file=f",
74     # etc.  Note that this also stops on "-3" or "-3.0", so if
75     # your option takes numeric values, you will need to handle this.
76     if ((arg[:2] == "--" and len(arg) > 2) or
77         (arg[:1] == "-" and len(arg) > 1 and arg[1] != "-")):
78       break
79     else:
80       value.append(arg)
81       del rargs[0]
82
83   setattr(parser.values, option.dest, value)
84
85 def parse_args():
86   """parse arguments, check validity and set defaults"""
87   parser = optparse.OptionParser(usage=usage)
88   parser.add_option('-p','--port', dest="port", default='', help="The port to connect to")
89   parser.add_option('-m','--machine', dest="machine", default='', help="The computer to connect to")
90   parser.add_option('-d','--directory', dest="directory", help="[Distant Mode] The APPLI_HOME path on the distant machine (must be used if Salome isn't on the local machine)")
91   parser.add_option('-u','--user', dest="user", default='', help="[Distant Mode] The user on the computer to connect to")
92   parser.add_option('-i','--infiles', dest="infiles", default=[], action="callback", callback=vararg_callback,
93                     help="[Distant Mode] The list of input files (blank separated) used in the Python script")
94   parser.add_option('-o','--outfiles', dest="outfiles", default=[], action="callback", callback=vararg_callback,
95                     help="[Distant Mode] The list of output files (blank separated) generated by the Python script")
96
97   args=sys.argv[1:]
98
99   script=""
100   if args:
101     script=args.pop()
102
103   options, args = parser.parse_args(args)
104
105   #check the arguments
106   if not os.path.exists(script):
107     print "ERROR: the script file is mandatory"
108     sys.exit(1)
109
110   machine=options.machine
111   port=options.port
112   user=options.user
113   infiles = options.infiles
114   outfiles = options.outfiles
115   directory=options.directory
116
117   mode="local"
118
119   if machine:
120     here=get_hostname()
121     if machine != here and machine != "localhost":
122       #SALOME server is on a remote computer
123       mode="remote"
124
125       if not user:
126         print "ERROR: the remote execution needs -u user argument"
127         sys.exit(1)
128
129       if not os.path.exists(os.path.join(appli_local,"runSession")):
130         if not directory:
131           print "ERROR: the remote execution without SALOME installation needs -d directory argument"
132           sys.exit(1)
133
134   return mode,user,machine,port,directory,infiles,outfiles,script
135
136 def copy_files(user,machine,script,infiles,outfiles,directory):
137   """modify script, copy files to remote computer and return lists of copied files"""
138
139   namescript=os.path.basename(script)
140   logname=os.getenv("LOGNAME",user)
141   tmp_script="/tmp/%s_%s_%s" % (logname,os.getpid(),namescript)
142   fscript=open(script)
143   script_text=fscript.read()
144   fscript.close()
145
146   list_infiles=[]
147   list_outfiles=[]
148
149   n=0
150   for infile in infiles:
151     # generate a temporary file name
152     namefile=os.path.basename(infile)
153     tmp_file="/tmp/%s_%s_i%s_%s" % (logname,os.getpid(),n,namefile)
154
155     #modify the salome script
156     script_text = re.sub(infile,tmp_file,script_text)
157
158     # copy the infile to the remote server (into /tmp)
159     cmd="scp %s %s@%s:%s" % (infile,user,machine,tmp_file)
160     print "[  SCP  ]",cmd
161     os.system(cmd)
162
163     list_infiles.append(tmp_file)
164     n=n+1
165
166   n=0
167   for outfile in outfiles:
168     # generate a temporary file name
169     namefile=os.path.basename(outfile)
170     tmp_file="/tmp/%s_%s_o%s_%s" % (logname,os.getpid(),n,namefile)
171
172     #modify the salome script
173     script_text = re.sub(outfile,tmp_file,script_text)
174
175     list_outfiles.append(tmp_file)
176     n=n+1
177
178   fscript=open(tmp_script,'w')
179   fscript.write(script_text)
180   fscript.close()
181
182   if directory:
183     #copy the salome script on the remote server
184     cmd="scp %s %s@%s:%s" % (tmp_script,user,machine,tmp_script)
185     print "[  SCP  ]",cmd
186     os.system(cmd)
187
188   return list_infiles, list_outfiles, tmp_script
189
190 def main():
191
192   mode,user,machine,port,directory,infiles,outfiles,script = parse_args()
193
194   tmp_script=script
195
196   print "mode:",mode
197
198   if mode == "remote":
199     list_infiles, list_outfiles, tmp_script = copy_files(user,machine,script,infiles,outfiles,directory)
200
201   #################################################
202   #          Execution                            #
203   #################################################
204   if directory:
205     print "[ REMOTE ]"
206
207     # execute runSession from the remote SALOME application
208     cmd="ssh %s@%s %s/runSession " % (user,machine,directory)
209     if port:
210       cmd=cmd+"-p %s "%port
211     cmd = cmd +"python " + tmp_script
212     print '[  SSH   ] ' + cmd
213     os.system(cmd)
214
215   else:
216     print "[ LOCAL ]"
217
218     # execute runSession from the local SALOME application
219     cmd="%s/runSession " % appli_local
220     if machine:
221       cmd=cmd+"-m %s "%machine
222     if port:
223       cmd=cmd+"-p %s "%port
224     cmd = cmd +"python " + tmp_script
225     print '[  SH   ] ' + cmd
226     os.system(cmd)
227
228   #################################################
229   #          Get remote files and clean           #
230   #################################################
231   if mode == "remote":
232     temp_files=list_infiles+list_outfiles
233
234     #get the outfiles
235     for outfile in outfiles:
236       remote_outfile=list_outfiles.pop(0)
237       cmd="scp %s@%s:%s %s" %(user,machine,remote_outfile,outfile)
238       print "[  SCP  ] "+cmd
239       os.system(cmd)
240
241     #clean temporary files
242     cmd="ssh %s@%s \\rm -f %s" % (user,machine," ".join(temp_files))
243     print '[  SSH   ] ' + cmd
244     os.system(cmd)
245     os.remove(tmp_script)
246
247 if __name__ == '__main__':
248   main()
249