Salome HOME
bug fix: omninames kill
[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   import getpass
141   logname = getpass.getuser()
142   tmp_script="/tmp/%s_%s_%s" % (logname,os.getpid(),namescript)
143   with open(script, 'r') as fscript:
144     script_text=fscript.read()
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
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   with open(tmp_script,'w') as fscript:
179     fscript.write(script_text)
180
181   if directory:
182     #copy the salome script on the remote server
183     cmd="scp %s %s@%s:%s" % (tmp_script,user,machine,tmp_script)
184     print "[  SCP  ]",cmd
185     os.system(cmd)
186
187   return list_infiles, list_outfiles, tmp_script
188
189 def main():
190
191   mode,user,machine,port,directory,infiles,outfiles,script = parse_args()
192
193   tmp_script=script
194
195   print "mode:",mode
196   print "user:",user
197   print "machine:",machine
198   print "port:",port
199   print "directory:",directory
200   print "infiles:",infiles
201   print "outfiles:",outfiles
202   print "script:",script
203
204   if mode == "remote":
205     list_infiles, list_outfiles, tmp_script = copy_files(user,machine,script,infiles,outfiles,directory)
206
207   #################################################
208   #          Execution                            #
209   #################################################
210   if mode == "remote":
211     print "[ REMOTE ]"
212
213     # execute runSession from the remote SALOME application
214     cmd="ssh %s@%s %s/runSession " % (user,machine,directory)
215     if port:
216       cmd=cmd+"-p %s "%port
217     cmd = cmd +"python " + tmp_script
218     print '[  SSH   ] ' + cmd
219     os.system(cmd)
220
221   else:
222     print "[ LOCAL ]"
223
224     # execute runSession from the local SALOME application
225     cmd="%s/runSession " % appli_local
226     if machine:
227       cmd=cmd+"-m %s "%machine
228     if port:
229       cmd=cmd+"-p %s "%port
230     cmd = cmd +"python " + tmp_script
231     print '[  SH   ] ' + cmd
232     os.system(cmd)
233
234   #################################################
235   #          Get remote files and clean           #
236   #################################################
237   if mode == "remote":
238     temp_files=list_infiles+list_outfiles+[tmp_script]
239
240     #get the outfiles
241     for outfile in outfiles:
242       remote_outfile=list_outfiles.pop(0)
243       cmd="scp %s@%s:%s %s" %(user,machine,remote_outfile,outfile)
244       print "[  SCP  ] "+cmd
245       os.system(cmd)
246
247     #clean temporary files
248     cmd="ssh %s@%s \\rm -f %s" % (user,machine," ".join(temp_files))
249     print '[  SSH   ] ' + cmd
250     os.system(cmd)
251     os.remove(tmp_script)
252
253 if __name__ == '__main__':
254   main()