def copy_flash(self): """Copy output/error to the flash directory. Return the filenames.""" prof = self.prof cfg = self._host_config flashcoll = prof.get_type('flash') assert len(flashcoll) > 0 flash = flashcoll[0] self.run.MkDir(flash.repr(), niverr='SILENT', verbose=True) df = {} for typ in ('output', 'error', 'export'): fname = FileName(self.flash(typ)) if not is_localhost2(self.host): fname.user = prof['username'][0] fname.host = prof['serveur'][0] else: fname.path = osp.join(get_home_directory(), fname.path) df[typ] = fname if cfg['result_on_client']: lf = [fname.repr() for fname in df.values()] self.run.Copy(flash.path, niverr='<A>_ALARM', *lf) else: cmd = 'mv -f %s %s' for fname in df.values(): self.run.Shell(cmd % (fname.path, flash.path), mach=self.prof['serveur'][0], user=prof['username'][0]) return df
def __init__(self, host, user, **kwargs): """Initialization""" self.host = host or local_host self.user = user or local_user self._is_localhost = is_localhost2(self.host, self.user) magic.log.info("BaseServer init host=%s user=%s", self.host, self.user)
def Ping(self, mach='', timeout=2): """Return True if 'mach' is responding. """ if is_localhost2(mach): return True iret, output = self.Shell(command['ping'] % { 'host': mach, 'timeout': timeout }) return iret == 0
def Shell(self, cmd, mach='', user='', **opts): """Execute a command shell on local or remote machine. Options : see local_shell """ #TODO use list type if type(cmd) in (list, tuple): cmd = ' '.join(cmd) iret = 1 # valeurs par défaut kargs = { 'verbose': self.verbose, 'bg': False, 'interact': False, 'follow_output': False, 'alt_comment': cmd, 'timeout': None, 'display_forwarding': False, } # surcharge par opts kargs.update(opts) proto = self.param['remote_shell_protocol'] # distant ? user = user or local_user distant = not is_localhost2(mach, user=user) self._dbg('remote command (%s <> %s and %s <> %s) ? %s' % (mach, local_host, user, local_user, distant)) if not distant: result = self.local_shell(cmd, **kargs) else: action = '' # pour recuperer correctement l'output, il faut des " et non des ' autour des # commandes sous "sh -c" et sous "xterm -e" if cmd.find('"') != -1: cmd = cmd.replace('"', '\\"') cmd = '"%s"' % cmd if proto == 'RSH': action = 'rsh -n -l ' + user + ' ' + mach + ' ' + cmd #elif proto == 'SSH': is the default else: options = "-n -o StrictHostKeyChecking=no -o BatchMode=yes" if kargs['timeout']: options += " -o 'ConnectTimeout=%s'" % kargs["timeout"] if kargs['display_forwarding']: options += " -X" action = "ssh %(options)s -l %(user)s %(host)s %(command)s" % { "user": user, "host": mach, "command": cmd, "options": options, } result = self.local_shell(action, **kargs) return result
def build_server(classname, host, user, **kwargs): """Build a server calling the specified protocol class. the argument type is necessary to choose a LocalServer variant. """ path = classname.split('.') if is_localhost2(host, user=user) and kwargs.get('type') is not None: magic.log.info("'%s' is the local host", host) if kwargs['type'] in (TYPES.COPY_TO, TYPES.COPY_FROM): sclass = LocalCopyServer else: sclass = LocalExecServer elif globals().get(path[-1]): sclass = globals()[path[-1]] else: # external server type sclass = get_plugin(classname) magic.log.debug("create %s with %s, %s, %s", sclass, host, user, kwargs) return sclass(host, user, **kwargs)
def Del(run, *args, **kwargs): """Kill a job and delete related files. """ if len(args) < 3: run.parser.error(_(u"'--%s' takes at least %d arguments (%d given)") % \ (run.current_action, 3, len(args))) elif len(args) > 4: run.parser.error(_(u"'--%s' takes at most %d arguments (%d given)") % \ (run.current_action, 4, len(args))) # 0. arguments njob, nomjob, mode = args[:3] if len(args) > 3: node = args[3] else: node = '' sent_signal = run['signal'] if kwargs.get('signal'): sent_signal = kwargs['signal'] delete_files = sent_signal == 'KILL' use_batch_cmd = False scheduler = None if mode == 'batch': scheduler = BatchSystemFactory(run) use_batch_cmd = sent_signal == 'KILL' or scheduler.supports_signal() # 1. retrieve the job status etat, diag, node, tcpu, wrk, queue = Func_actu(run, njob, nomjob, mode) run.DBG(u"actu returns : etat/diag/node/tcpu/wrk/queue", (etat, diag, node, tcpu, wrk, queue)) # 2. send the signal if etat in ('RUN', 'SUSPENDED', 'PEND'): if use_batch_cmd: iret = scheduler.signal_job(njob, sent_signal) if iret != 0: run.Sortie(4) else: numpr, psout = '', '' # get process id if node == '_': # try on localhost node = '' if node != '_': jret, psout = run.Shell(run['ps_pid'], mach=node) exp = re.compile('^ *([0-9]+) +(.*)\-\-num_job=%s.*\-\-mode=%s' \ % (njob, mode), re.MULTILINE) res = exp.findall(psout) res.reverse() # the relevant process should be the last one run.DBG(u"processes :", res) for numj, cmd in res: # "sh -c" is automatically added by os.system if cmd.find(shell_cmd) < 0 and cmd.find("sh -c") < 0: numpr = int(numj) run.DBG(u"Signal will be sent to process : %s" % numpr) break if numpr == '': # try to kill its as_run parent (but USR1 will not stop as_run) sent_signal = 'KILL' exp = re.compile('^ *([0-9]+) +(.*as_run.*\-\-num_job=+%s.*)' \ % njob, re.M) res = exp.findall(psout) res.reverse( ) # the relevant process should be the last one run.DBG(u"as_run processes :", res) for numj, cmd in res: # python run by bin/as_run if cmd.find('python') > -1: numpr = int(numj) run.DBG(u"Signal will be sent to process : %s" % numpr) break if numpr != '': if is_localhost2(node): os.kill(numpr, getattr(signal, 'SIG%s' % sent_signal)) else: iret, psout = run.Shell('kill -%s %s' % (sent_signal, numpr), mach=node) else: run.DBG(u'<job.Del> process not found :', psout, u'node = %s' % node, all=True) # 3. delete files if delete_files: l_fich = glob.glob(osp.join(run['flasheur'], '%s.?%s' % (nomjob, njob))) for f in l_fich: run.Delete(f)
def IsRemote(self, path): """Return True if 'path' seems to be on a remote host. NB : we suppose that host and host.domain are identical. """ dico = self.filename2dict(path) return not is_localhost2(dico["mach"])
def soumbtc_interactif(self, fbtc): """Run btc in interactive mode. """ self.jobid = self.pid # commandes cmd_batch = '%(fbtc)s 1> %(output)s 2> %(error)s' cmd_interactif = '%(fbtc)s 2> %(error)s | tee %(output)s' node = self.dict_info['node'] dico = { 'fbtc': fbtc, 'output': self.flash('output'), 'error': self.flash('error'), } # follow output or not xterm = '' if self.prof['follow_output'][0] in YES_VALUES: xterm = self.run['terminal'] if self.prof['depart'][0] != '' or xterm == '': cmd = cmd_batch % dico else: cmd = cmd_interactif % dico # delayed start if self.prof['depart'][0] != '': cmd = "echo '%s' | at %s" % (cmd, self.prof['depart'][0]) elif xterm != '': if re.search('@E', xterm) == None: xterm = xterm + ' -e @E' cmd = xterm.replace('@E', '%s "%s"' % (shell_cmd, cmd)) # run on another node distant = not is_localhost2(node) if not distant: # check xterm command if xterm != '': term = xterm.split()[0] if not os.access(term, os.X_OK): print3(_(u"Not an executable : %s") % term) return 7, '', 'unknown' else: # check node connection iret, output = self.run.Shell('echo hello', mach=node) if output.find('hello') < 0: print3(output) print3( _(u"Connection failure to %s (from %s)") % (node, self.prof['serveur'][0])) return 6, '', 'unknown' # background is not possible if display forwarding is required # (the connection must stay alive) need_display = xterm != '' background = (not need_display) \ or same_hosts2(self.prof['mclient'][0], node, self.prof['uclient'][0], self.prof['username'][0]) kret, output = self.run.Shell(cmd, mach=node, bg=background, display_forwarding=need_display) return 0, self.jobid, 'interactif'