1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
4 # Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
5 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
26 from optparse import OptionParser
27 from NSparam import getNSparams
31 from salomeContextUtils import getScriptsAndArgs, formatScriptsAndArgs
33 # Use to display newlines (\n) in epilog
34 class MyParser(OptionParser):
35 def format_epilog(self, formatter):
39 class SessionParameters:
40 def __init__(self, mode, port, machine, user, directory):
43 self.machine = machine
45 self.directory = directory
48 def configureSession(args=None):
51 usage = "Usage: %prog [options] [command]"
53 If the command is not given a shell is opened; else execute the given command.
54 Command may be a series of Python scripts with arguments: [PYTHON_FILE [args] [PYTHON_FILE [args]...]]
55 Python file arguments, if any, must be comma-separated (without blank characters) and prefixed by "args:" (without quotes), e.g. myscript.py args:arg1,arg2=val,...
57 If PORT and MACHINE are not given, try to connect to the last active session on the local machine.
58 If PORT and MACHINE are given, try to connect to the remote session associated with PORT on MACHINE.
59 If MACHINE is not given, try to connect to the session associated to PORT on the local machine.
60 If PORT is not given, try to connect to the remote session associated to port 2810 on MACHINE.
62 If MACHINE is remote, the following options MUST be provided:
63 * DIRECTORY: The full path to the salome command on remote machine.
64 * USER: The user on the computer to connect to.
66 parser = MyParser(usage=usage, epilog=epilog)
67 parser.add_option("-p", "--port", metavar="<port>", default=0,
68 action="store", type="string", dest="port",
69 help="The port to connect to."
71 parser.add_option("-m", "--machine", metavar="<machine>", default=0,
72 action="store", type="string", dest="host",
73 help="The machine to connect to."
75 parser.add_option('-d', '--directory', dest="directory", default=None,
76 help="[Remote mode] The full path to the salome command on remote machine."
78 parser.add_option('-u', '--user', dest="user", default=None,
79 help="[Remote mode] The user on the computer to connect to."
82 (options, args) = parser.parse_args(args)
90 # :GLITCH: this code defines specific environment variables (OMNIORB_CONFIG, NSPORT,
91 # NSHOST) which are later used by other modules. Working, but not really "safe"...
94 # neither MACHINE nor PORT are given
95 # --- set omniORB configuration to current session if any
96 omniorbUserPath = os.environ['OMNIORB_USER_PATH']
97 fileOmniConfig = omniorbUserPath + '/.omniORB_' + os.environ['USER'] + '_last.cfg'
98 if os.path.isfile(fileOmniConfig):
99 os.environ['OMNIORB_CONFIG'] = fileOmniConfig
100 # --- set environment variables for port and hostname of NamingService
101 host, port = getNSparams()
107 # only MACHINE is given
109 _writeConfigFile(port, host)
114 host = socket.gethostname()
115 # both MACHINE and PORT are given
116 _writeConfigFile(port, host)
118 os.environ['NSPORT'] = port
119 os.environ['NSHOST'] = host
121 # determine running mode, taht is either 'local' or 'remote'
122 from salomeContextUtils import getHostname
125 if host != here and host != "localhost" and host != "no_host":
128 params = SessionParameters(mode, port, host, options.user, options.directory)
132 # --- set the OMNIORB_CONFIG file and environment relative to this run of SALOME
133 def _writeConfigFile(port, host):
134 path = os.environ['OMNIORB_USER_PATH']
135 kwargs = {'with_username' : os.environ['USER']}
137 from ORBConfigFile import writeORBConfigFile
138 [ filename, msgSize ] = writeORBConfigFile(path, host, port, kwargs)
140 os.environ['OMNIORB_CONFIG'] = filename
143 # command looks like a Bash command-line:
144 # script1.py [args] ; script2.py [args] ; ...
145 def __runLocalSession(command):
148 if sys.platform == "win32":
150 command = command.split(sep)
154 single_cmd = cmd.strip().split(' ')
155 proc = subprocess.Popen(single_cmd)
156 (stdoutdata, stderrdata) = proc.communicate() # Wait for process to terminate
158 outmsg.append(stdoutdata)
160 errmsg.append(stderrdata)
162 if proc.returncode != 0:
163 errmsg.append("Error raised when executing command: %s\n"%cmd)
165 sys.stdout.write("".join(outmsg))
167 sys.stderr.write("".join(errmsg))
168 sys.exit(proc.returncode)
170 return ("".join(outmsg), "".join(errmsg))
172 absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
173 cmd = ["/bin/bash", "--rcfile", absoluteAppliPath + "/.bashrc" ]
174 proc = subprocess.Popen(cmd, shell=False, close_fds=True)
175 return proc.communicate()
178 def __copyFiles(user, machine, script, infiles, outfiles):
179 """Modify script, copy files to remote computer and return lists of copied files."""
181 namescript = os.path.basename(script)
183 logname = getpass.getuser()
184 tmp_script = "/tmp/%s_%s_%s" % (logname, os.getpid(), namescript)
185 with open(script, 'r') as fscript:
186 script_text = fscript.read()
191 for infile in infiles:
192 # generate a temporary file name
193 namefile = os.path.basename(infile)
194 tmp_file = "/tmp/%s_%s_i%s_%s" % (logname, os.getpid(), n, namefile)
196 # modify the salome script
197 script_text = re.sub(infile, tmp_file, script_text)
199 # copy the infile to the remote server
200 cmd = "scp %s %s@%s:%s" % (infile, user, machine, tmp_file)
204 list_infiles.append(tmp_file)
208 for outfile in outfiles:
209 # generate a temporary file name
210 namefile = os.path.basename(outfile)
211 tmp_file = "/tmp/%s_%s_o%s_%s" % (logname, os.getpid(), n, namefile)
213 # modify the salome script
214 script_text = re.sub(outfile, tmp_file, script_text)
216 list_outfiles.append(tmp_file)
220 with open(tmp_script,'w') as fscript:
221 fscript.write(script_text)
223 # copy the salome script on the remote server
224 cmd = "scp %s %s@%s:%s" % (tmp_script, user, machine, tmp_script)
228 return list_infiles, list_outfiles, tmp_script
231 # sa_obj is a ScriptAndArgs object (from salomeContextUtils)
232 def __runRemoteSession(sa_obj, params):
234 print "ERROR: The user login on remote machine MUST be given."
236 if not params.directory:
237 print "ERROR: The remote directory MUST be given."
240 # sa_obj.script may be 'python script.py' --> only process .py file
241 header = " ".join(sa_obj.script.split()[:-1])
242 script = sa_obj.script.split()[-1]
244 tmp_in, tmp_out, tmp_script = __copyFiles(params.user, params.machine, script, sa_obj.args or [], sa_obj.out or [])
246 # execute command on the remote SALOME application
247 command = "ssh %s@%s %s/salome shell " % (params.user, params.machine, params.directory)
249 command = command + "-p %s "%params.port
250 command = command + " %s %s args:%s"%(header, tmp_script, ",".join(tmp_in))
251 print '[ SSH ] ' + command
254 # Get remote files and clean
255 temp_files = tmp_in + tmp_out + [tmp_script]
258 for outfile in (sa_obj.out or []):
259 remote_outfile = tmp_out.pop(0)
260 command = "scp %s@%s:%s %s" %(params.user, params.machine, remote_outfile, outfile)
261 print "[ SCP ] " + command
264 # clean temporary files
265 command = "ssh %s@%s \\rm -f %s" % (params.user, params.machine, " ".join(temp_files))
266 print '[ SSH ] ' + command
268 os.remove(tmp_script)
272 def runSession(params, args):
273 scriptArgs = getScriptsAndArgs(args)
274 command = formatScriptsAndArgs(scriptArgs)
276 if params.mode == "local":
277 command = formatScriptsAndArgs(scriptArgs)
278 return __runLocalSession(command)
280 elif params.mode == "remote":
281 for sa_obj in scriptArgs:
282 __runRemoteSession(sa_obj, params)