Salome HOME
Merge branch 'V7_5_BR'
[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 ###############################################
26 ############### IMPORTANT NOTE ################
27 ###############################################
28 # The runSalomeScript script is obsolete.     #
29 # Please consider the new salome launcher.    #
30 ###############################################
31
32 import os,sys,optparse
33 import socket,shutil
34 import re
35
36 usage="""
37         Connect to a SALOME session (local or remote) and execute a Python script with data files in argument (optional)
38
39         Usage: %prog [ options ] script
40
41           script           : The Python script to execute in the SALOME session
42
43         SALOME SESSION
44         --------------
45         If PORT and MACHINE are not given, try to connect to the last active session on the local machine
46         If PORT and MACHINE are given, try to connect to the remote session associated with PORT on MACHINE
47         If MACHINE is not given, try to connect to the session associated to PORT on the local machine
48         If PORT is not given, try to connect to the remote session associated to port 2810 on MACHINE
49
50         If MACHINE isn't localhost or hostname, USER is needed
51
52         If Salome isn't installed on the local machine, use APPLI_DIST to execute a distant session
53
54
55         INPUTS AND OUPUTS
56         -----------------
57         script is needed in all case
58         INPUT and OUTPUT are used only when Salome isn't on local machine. It defines a list of script (full path, blank separated)
59         Actions done with these two lists are :
60         - adjustment of path in a temporary script file
61         - copy of the input files and script file on the distant machine
62
63 """
64
65 appli_local=os.path.realpath(os.path.dirname(__file__))
66
67 def get_hostname():
68   return socket.gethostname().split('.')[0]
69
70 def vararg_callback(option, opt_str, value, parser):
71   """optparse callback for variable length arguments"""
72   assert value is None
73
74   done = 0
75   value = []
76   rargs = parser.rargs
77   while rargs:
78     arg = rargs[0]
79
80     # Stop if we hit an arg like "--foo", "-a", "-fx", "--file=f",
81     # etc.  Note that this also stops on "-3" or "-3.0", so if
82     # your option takes numeric values, you will need to handle this.
83     if ((arg[:2] == "--" and len(arg) > 2) or
84         (arg[:1] == "-" and len(arg) > 1 and arg[1] != "-")):
85       break
86     else:
87       value.append(arg)
88       del rargs[0]
89
90   setattr(parser.values, option.dest, value)
91
92 def parse_args():
93   """parse arguments, check validity and set defaults"""
94   parser = optparse.OptionParser(usage=usage)
95   parser.add_option('-p','--port', dest="port", default='', help="The port to connect to")
96   parser.add_option('-m','--machine', dest="machine", default='', help="The computer to connect to")
97   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)")
98   parser.add_option('-u','--user', dest="user", default='', help="[Distant Mode] The user on the computer to connect to")
99   parser.add_option('-i','--infiles', dest="infiles", default=[], action="callback", callback=vararg_callback,
100                     help="[Distant Mode] The list of input files (blank separated) used in the Python script")
101   parser.add_option('-o','--outfiles', dest="outfiles", default=[], action="callback", callback=vararg_callback,
102                     help="[Distant Mode] The list of output files (blank separated) generated by the Python script")
103
104   args=sys.argv[1:]
105
106   script=""
107   if args:
108     script=args.pop()
109
110   options, args = parser.parse_args(args)
111
112   #check the arguments
113   if not os.path.exists(script):
114     print "ERROR: the script file is mandatory"
115     sys.exit(1)
116
117   machine=options.machine
118   port=options.port
119   user=options.user
120   infiles = options.infiles
121   outfiles = options.outfiles
122   directory=options.directory
123
124   mode="local"
125
126   if machine:
127     here=get_hostname()
128     if machine != here and machine != "localhost":
129       #SALOME server is on a remote computer
130       mode="remote"
131
132       if not user:
133         print "ERROR: the remote execution needs -u user argument"
134         sys.exit(1)
135
136       if not os.path.exists(os.path.join(appli_local,"runSession")):
137         if not directory:
138           print "ERROR: the remote execution without SALOME installation needs -d directory argument"
139           sys.exit(1)
140
141   return mode,user,machine,port,directory,infiles,outfiles,script
142
143 def copy_files(user,machine,script,infiles,outfiles,directory):
144   """modify script, copy files to remote computer and return lists of copied files"""
145
146   namescript=os.path.basename(script)
147   import getpass
148   logname = getpass.getuser()
149   tmp_script="/tmp/%s_%s_%s" % (logname,os.getpid(),namescript)
150   with open(script, 'r') as fscript:
151     script_text=fscript.read()
152
153   list_infiles=[]
154   list_outfiles=[]
155
156   n=0
157   for infile in infiles:
158     # generate a temporary file name
159     namefile=os.path.basename(infile)
160     tmp_file="/tmp/%s_%s_i%s_%s" % (logname,os.getpid(),n,namefile)
161
162     #modify the salome script
163     script_text = re.sub(infile,tmp_file,script_text)
164
165     # copy the infile to the remote server
166     cmd="scp %s %s@%s:%s" % (infile,user,machine,tmp_file)
167     print "[  SCP  ]",cmd
168     os.system(cmd)
169
170     list_infiles.append(tmp_file)
171     n=n+1
172
173   n=0
174   for outfile in outfiles:
175     # generate a temporary file name
176     namefile=os.path.basename(outfile)
177     tmp_file="/tmp/%s_%s_o%s_%s" % (logname,os.getpid(),n,namefile)
178
179     #modify the salome script
180     script_text = re.sub(outfile,tmp_file,script_text)
181
182     list_outfiles.append(tmp_file)
183     n=n+1
184
185   with open(tmp_script,'w') as fscript:
186     fscript.write(script_text)
187
188   if directory:
189     #copy the salome script on the remote server
190     cmd="scp %s %s@%s:%s" % (tmp_script,user,machine,tmp_script)
191     print "[  SCP  ]",cmd
192     os.system(cmd)
193
194   return list_infiles, list_outfiles, tmp_script
195
196 def main():
197
198   mode,user,machine,port,directory,infiles,outfiles,script = parse_args()
199
200   tmp_script=script
201
202   if mode == "remote":
203     list_infiles, list_outfiles, tmp_script = copy_files(user,machine,script,infiles,outfiles,directory)
204
205   #################################################
206   #          Execution                            #
207   #################################################
208   if mode == "remote":
209     print "[ REMOTE ]"
210
211     # execute runSession from the remote SALOME application
212     cmd="ssh %s@%s %s/runSession " % (user,machine,directory)
213     if port:
214       cmd=cmd+"-p %s "%port
215     cmd = cmd +"python " + tmp_script
216     print '[  SSH   ] ' + cmd
217     os.system(cmd)
218
219   else:
220     print "[ LOCAL ]"
221
222     # execute runSession from the local SALOME application
223     cmd="%s/runSession " % appli_local
224     if machine:
225       cmd=cmd+"-m %s "%machine
226     if port:
227       cmd=cmd+"-p %s "%port
228     cmd = cmd +"python " + tmp_script
229     print '[  SH   ] ' + cmd
230     os.system(cmd)
231
232   #################################################
233   #          Get remote files and clean           #
234   #################################################
235   if mode == "remote":
236     temp_files=list_infiles+list_outfiles+[tmp_script]
237
238     #get the outfiles
239     for outfile in outfiles:
240       remote_outfile=list_outfiles.pop(0)
241       cmd="scp %s@%s:%s %s" %(user,machine,remote_outfile,outfile)
242       print "[  SCP  ] "+cmd
243       os.system(cmd)
244
245     #clean temporary files
246     cmd="ssh %s@%s \\rm -f %s" % (user,machine," ".join(temp_files))
247     print '[  SSH   ] ' + cmd
248     os.system(cmd)
249     os.remove(tmp_script)
250
251 if __name__ == '__main__':
252   main()