This file is indexed.

/usr/share/pyshared/asrun/plugins/default.py is in code-aster-run 1.13.1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
# -*- coding: utf-8 -*-

# ==============================================================================
# COPYRIGHT (C) 1991 - 2003  EDF R&D                  WWW.CODE-ASTER.ORG
# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
# (AT YOUR OPTION) ANY LATER VERSION.
#
# THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
# WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
# GENERAL PUBLIC LICENSE FOR MORE DETAILS.
#
# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
#    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
# ==============================================================================

"""
This module defines the default schemes.

Additionnal modules can be added to define others schemes to extend
the capabilities of asrun.

These plugins can be added in any directory listed in PYTHONPATH.
But it's recommended to place them in etc/codeaster/plugins because
the modules added in this directory will be kept during updates of asrun.
"""

import os
import os.path as osp

from asrun.common.i18n  import _
from asrun.core         import magic
from asrun.mystring     import print3
from asrun.calcul       import parse_submission_result, parse_consbtc
from asrun.job          import parse_actu_result, print_actu_result
from asrun.profil       import AsterProfil
from asrun.core.configuration import get_plt_exec_name
from asrun.common_func  import flash_filename, edit_file
from asrun.common.utils import get_absolute_path, unique_basename
from asrun.common.sysutils import local_user, local_full_host, get_home_directory
from asrun.core.server  import build_server_from_profile, TYPES
from asrun.rex          import parse_issue_file
from asrun.profile_modifier import apply_special_service



def serv(prof, args, print_output=True, **kwargs):
    """Call --serv action on a server."""
    run = magic.run
    num_job = kwargs.get('num_job', run['num_job'])
    # decode special service
    serv, prof = apply_special_service(prof, run, on_client_side=True)
    if serv != "":
        magic.log.info(_(u"special service : %s"), serv)
    # set studyid (if already defined in prof, use this one)
    studyid = prof['studyid'][0]
    if studyid == '':
        studyid = "%s-%s" % (num_job, prof['mclient'][0].split('.')[0])
    # read server informations
    sexec = build_server_from_profile(prof, TYPES.EXEC)
    scopy = build_server_from_profile(prof, TYPES.COPY_TO, jobid=studyid)
    magic.log.info(_(u"prepare execution for %s@%s"), sexec.user, sexec.host)

    # prepare export for execution with all files present in the remote directory
    fprof = osp.join(run['tmp_user'], "%s.export" % studyid)
    forig = osp.join(run['tmp_user'], "%s.orig.export" % studyid)
    prof.set_filename(forig)
    prof.WriteExportTo(forig)
    run.ToDelete(fprof)
    run.ToDelete(forig)

    iret, remote_prof = copy_datafiles_on_server(prof, studyid, fprof)
    if iret != 0:
        return iret, ''

    # launch the study
    cmd = [osp.join(sexec.get_aster_root(), "bin",
                    get_plt_exec_name(remote_prof.get_platform(), "as_run")), ]
    cmd.append("--serv")
    cmd.append("--num_job=%s" % studyid)
    cmd.extend(run.get_rcdir_arg())
    cmd.append(remote_prof.get_filename())

    iret, output, err = sexec.exec_command(cmd, display_forwarding=True)
    run.DBG("******************** OUTPUT of as_run --serv ********************",output,
            "******************** ERROR of as_run --serv ********************", err,
            "******************** END of as_run --serv ********************",
            all=True, prefix="    ")
    jobid, queue, stid2 = parse_submission_result(output)
    run.DBG("The server returns %s and studyid is set to %s" % (stid2, studyid))
    if print_output:
        print3("JOBID=%s QUEUE=%s STUDYID=%s" % (jobid, queue, studyid))
    btc = parse_consbtc(output)
    if btc is not None and print_output:
        print3("BTCFILE=%s" % btc)
    if iret != 0:
        output += os.linesep.join([output,
            "******************** ERROR of as_run --serv ********************", err])
    return iret, output


def get_results(prof, args, **kwargs):
    """Download result files from the server."""
    run = magic.run

    magic.log.info(_(u"get result files from the server"))
    # read studyid
    study_prof = get_study_export(prof)
    if study_prof is None:
        return 4
    studyid = study_prof['studyid'][0]
    forig = osp.join(run['tmp_user'], "%s.orig.export" % studyid)

    # read server informations
    scopy = build_server_from_profile(study_prof, TYPES.COPY_FROM, jobid=studyid)
    # get original export
    iret = scopy.copyfrom(forig)
    if iret != 0:
        magic.log.warn(_(u"the results seem already downloaded."))
        return iret
    oprof = AsterProfil(forig, run)
    magic.run.DBG("original export :\n%s" % repr(oprof), all=True)

    run_on_localhost = scopy.is_localhost()
    # copy results files
    if not run_on_localhost:
        local_resu = oprof.get_result().get_on_serv(local_full_host)
        local_nom, local_other = local_resu.get_type('nom', with_completion=True)
        iret = scopy.copyfrom(convert=unique_basename, *local_other.topath())
        jret = scopy.copyfrom(*local_nom.topath())
        iret = max(iret, jret)
        local_resu = local_resu.topath()
    else:
        local_resu = []

    remote_resu = oprof.get_result().get_on_serv(scopy.host, scopy.user).topath()
    all = set(oprof.get_result().topath())
    all.difference_update(local_resu)
    all.difference_update(remote_resu)
    if len(all) > 0:
        magic.log.warn(_(u"files on a third host should have been copied "
            "at the end of the calculation (if possible) : %s"),
            [e.repr() for e in all])

    # remove remote repository
    if iret == 0:
        scopy.delete_proxy_dir()
    return iret


def get_study_export(prof):
    """Return the original export."""
    run = magic.run
    # read server informations
    serv = build_server_from_profile(prof, TYPES.COPY_FROM)

    jobid = prof['jobid'][0]
    jobname = prof['nomjob'][0]
    mode = prof['mode'][0]
    # flasheur is in the home directory
    dirname, fname = osp.split(flash_filename("flasheur", jobname, jobid, "export", mode))
    run.DBG("export file in %s is named %s" % (dirname, fname))

    # copy export file locally
    serv.set_proxy_dir(dirname)
    dst = osp.join(run['tmp_user'], 'flasheur_%s' % serv.host, fname)
    iret = serv.copyfrom(dst)
    if iret != 0:
        return None

    # read studyid
    study_prof = AsterProfil(dst, run)
    return study_prof


def call_generic_service(action, serv, prof, args, options={}):
    """Generic function : call the service on the given server."""
    # BE CAREFULL : first argument of `args` is ignored (supposed to be equal to `prof`)
    # the server is created by the caller essentially to give relevant progress informations
    # launch the service
    run = magic.run
    cmd = [osp.join(serv.get_aster_root(), "bin",
                    get_plt_exec_name(prof.get_platform(), "as_run")), ]
    cmd.append("--" + action)
    cmd.extend(run.get_rcdir_arg())
    for key, val in options.items():
        if val is True:
            val = ""
        else:
            val = "=%s" % val
        cmd.append("--%s%s" % (key, val))
    cmd.extend(args[1:])

    iret, output, err = serv.exec_command(cmd)
    run.DBG("******************** OUTPUT of as_run --%s ********************" % action, output,
            #"******************** ERROR of as_run --%s ********************" % action, err,
            "******************** END of as_run --%s ********************" % action,
            all=True, prefix="    ")
    if iret != 0:
        output += os.linesep.join([output,
            "******************** ERROR of as_run --%s ********************" % action, err])
    return iret, output, err


def copy_datafiles_on_server(prof, studyid, fprof):
    """Copy data files on the server, relocate the export and write it (locally)
    into 'fprof'. Return the relocated export."""
    # read server informations
    sexec = build_server_from_profile(prof, TYPES.EXEC)
    scopy = build_server_from_profile(prof, TYPES.COPY_TO, jobid=studyid)
    forig = prof.get_filename()
    magic.log.debug("original export name is %s", forig)
    magic.run.DBG("original export :\n%s" % repr(prof), all=True)

    run_on_localhost = sexec.is_localhost()
    remote_prof = prof.copy()
    if not run_on_localhost:
        remote_prof.relocate(local_full_host, scopy.get_proxy_dir(),
                             convert=unique_basename)
    remote_prof.relocate(sexec.host, convert=unique_basename)
    remote_prof['studyid'] = studyid
    remote_prof.set_filename(fprof)
    remote_prof.WriteExportTo(fprof)
    magic.run.DBG("remote export :\n%s" % repr(remote_prof), all=True)

    # copy data files
    # - local_data : files which are on localhost and to copy on the compute server
    all_data = prof.get_data()
    if not run_on_localhost:
        local_data = all_data.get_on_serv(local_full_host).topath()
    else:
        local_data = []
    # - remote_data : these files are already on the server, use them directly
    remote_data = all_data.get_on_serv(sexec.host, sexec.user).topath()
    # - foreign_data : if they are on a foreign server (not localhost or
    #   compute server), we can :
    #   - first copy them locally, and send them to the compute server.
    #   - or try to copy them from the compute server (<<< let this choice right now).
    all = set(all_data.topath())
    all.difference_update(local_data)
    all.difference_update(remote_data)
    if len(all) > 0:
        magic.log.warn(_(u"files on a third host may be unavailable "
                          "for calculation : %s"), all)

    # copy files on the server
    magic.log.info(_(u"copy export files..."))
    iret = scopy.copyto(fprof, forig)
    magic.log.info(_(u"copy data files..."))
    iret = scopy.copyto(convert=unique_basename, *local_data)

    # set remote filename
    remote_prof.set_filename(scopy.get_remote_filename(fprof))
    return iret, remote_prof


def actu(prof, args, **kwargs):
    """Default schema for 'actu' action."""
    return actu_and_results(prof, args, **kwargs)


def actu_and_results(prof, args, print_output=True, **kwargs):
    """Call --actu action on a server
    + call automatically --get_results if the job is ended."""
    iret, output = _call_actu(prof, args)
    result = parse_actu_result(output)
    if print_output:
        print_actu_result(*result)
    if iret == 0 and result[0] == "ENDED":
        iret2 = get_results(prof, args)
    return iret, output


def actu_simple(prof, args, print_output=True, **kwargs):
    """Call --actu action on a server"""
    iret, output = _call_actu(prof, args)
    result = parse_actu_result(output)
    if print_output:
        print_actu_result(*result)
    return iret, output


def _call_actu(prof, args):
    """Call --actu action on a server"""
    jobid = prof['jobid'][0]
    jobname = prof['nomjob'][0]
    mode = prof['mode'][0]
    targs = (None, jobid, jobname, mode)

    # read server informations
    serv = build_server_from_profile(prof, TYPES.EXEC)

    magic.log.info(_(u"ask the server for the job status"))
    iret, output, err = call_generic_service("actu", serv, prof, targs)
    magic.log.debug("server returns %s", output)
    result = parse_actu_result(output)
    magic.log.info(_(u"job status is %s"), result[0])
    return iret, output


def stop_del(prof, args, **kwargs):
    """Call --del action on a server"""
    # retreive the study export before it would be removed
    study_prof = get_study_export(prof)

    jobid = prof['jobid'][0]
    jobname = prof['nomjob'][0]
    mode = prof['mode'][0]
    node = prof['noeud'][0]
    targs = (None, jobid, jobname, mode, node)
    signal = kwargs.get('signal', magic.run['signal'])

    # read server informations
    serv = build_server_from_profile(prof, TYPES.EXEC)
    magic.log.info(_(u"ask the server to cancel the job and remove its "
                      "files from 'flasheur'"))
    iret, output, err = call_generic_service("del", serv, prof, targs,
        { 'signal' : signal })

    # stop here if signal!=KILL or the study id have not been retreived
    if signal != 'KILL' or study_prof is None:
        return iret

    # remove remote repository
    studyid = study_prof['studyid'][0]
    scopy = build_server_from_profile(study_prof, TYPES.COPY_FROM, jobid=studyid)
    scopy.delete_proxy_dir()
    return iret


def purge_flash(prof, args, **kwargs):
    """Call --purge_flash action on a server"""
    # read server informations
    serv = build_server_from_profile(prof, TYPES.EXEC)

    iret, output, err = call_generic_service("purge_flash", serv, prof, args)
    return iret


def tail(prof, args, print_output=True, **kwargs):
    """Call --tail action on a server"""
    jobid = prof['jobid'][0]
    jobname = prof['nomjob'][0]
    mode = prof['mode'][0]
    nbline = prof['tail_nbline'][0]
    regexp = prof['tail_regexp'][0]
    targs = (None, jobid, jobname, mode, 'None', nbline, regexp)

    # read server informations
    serv = build_server_from_profile(prof, TYPES.EXEC)

    options = { 'result_to_output' : True }
    iret, output, err = call_generic_service("tail", serv, prof, targs, options)
    if print_output:
        print3(output)
    # not expected in output
    magic.run.PrintExitCode = False
    return iret, output


def info(prof, args, print_output=True, **kwargs):
    """Call --info action on a server"""
    # read server informations
    serv = build_server_from_profile(prof, TYPES.EXEC)

    magic.log.info(_(u"retreive configuration informations of the server"))
    iret, output, err = call_generic_service("info", serv, prof, args)
    if print_output:
        print3(output)
    # already in output
    magic.run.PrintExitCode = False
    return iret, output


def edit(prof, args, **kwargs):
    """Default schema for 'edit' action."""
    return local_edit(prof, args, **kwargs)


def remote_edit(prof, args, **kwargs):
    """Call --edit action on a server by opening an editor on the
    server."""
    #XXX --edit does not yet support display argument: remote_edit may not work
    # maybe by adding a sleeping time...?
    action = "edit"
    jobid = prof['jobid'][0]
    jobname = prof['nomjob'][0]
    mode = prof['mode'][0]
    typ = prof['edit_type'][0]
    displ = prof['display'][0]

    # read server informations
    serv = build_server_from_profile(prof, TYPES.EXEC)

    if serv.support_display_forwarding():
        # --edit will use os.environ['DISPLAY']
        # but this will not work if ssh is run in background...
        displ = "None:0"

    # launch the service
    cmd = [osp.join(serv.get_aster_root(), "bin",
                    get_plt_exec_name(prof.get_platform(), "as_run")), ]
    cmd.append("--" + action)
    cmd.extend(magic.run.get_rcdir_arg())
    targs = (jobid, jobname, mode, typ)
    cmd.extend(targs)

    iret, output, err = serv.exec_command(cmd, display_forwarding=True)
    magic.run.DBG("******************** OUTPUT of as_run --%s ********************" % action, output,
            "******************** END of as_run --%s ********************" % action,
            all=True, prefix="    ")
    return iret


def local_edit(prof, args, **kwargs):
    """Call --edit action on a server by using a local editor after
    copying file if it's remote."""
    run = magic.run
    jobid = prof['jobid'][0]
    jobname = prof['nomjob'][0]
    mode = prof['mode'][0]
    typ = prof['edit_type'][0]
    to_output = kwargs.get('result_to_output', run['result_to_output'])

    iret = 0
    # read server informations
    serv = build_server_from_profile(prof, TYPES.COPY_FROM)

    # flasheur is in the home directory
    dirname, fname = osp.split(flash_filename("flasheur", jobname, jobid, typ, mode))
    run.DBG("file to edit is in %s named %s" % (dirname, fname))

    # copy from dirname if not on localhost
    if not serv.is_localhost():
        serv.set_proxy_dir(dirname)
        dst = osp.join(run['tmp_user'], 'flasheur_%s' % serv.host, fname)
        is_agla_astout = prof['nomjob'][0].startswith('pre_eda') \
                      or prof['nomjob'][0].startswith('asrest')
        if not osp.exists(dst) or is_agla_astout:
            iret = serv.copyfrom(dst)
    else:
        iret = 0
        dst = osp.join(get_home_directory(), dirname, fname)

    if iret == 0 and not to_output:
        magic.log.info(_(u"edit file %s"), dst)
        edit_file(run, dst)
    return iret


def sendmail(prof, args, **kwargs):
    """Call --sendmail action on a server.
    Allow to send a mail even if it's not configured on localhost."""
    # put the file on the server
    run = magic.run
    num_job = kwargs.get('num_job', run['num_job'])
    to = kwargs.get('report_to', run['report_to'])
    jobid = '%s-%s' % (num_job, "sendmail")
    # read server informations
    sexec = build_server_from_profile(prof, TYPES.EXEC)
    scopy = build_server_from_profile(prof, TYPES.COPY_TO, jobid=jobid)

    # copy text file
    scopy.copyto(args[1])
    rfile = scopy.get_remote_filename(args[1])
    targs = (None, rfile, )

    iret, output, err = call_generic_service("sendmail", sexec, prof, targs,
        { 'report_to' : to })
    scopy.delete_proxy_dir()
    return iret


def get_export(prof, args, print_output=True, **kwargs):
    """Call --get_export action on a server."""
    # read server informations
    serv = build_server_from_profile(prof, TYPES.EXEC)
    vers = kwargs.get('vers', magic.run['aster_vers'])

    iret, output, err = call_generic_service("get_export", serv, prof, args,
        { 'vers' : vers })
    if print_output:
        print3(output)
    return iret, output


def serv_with_reverse_access(prof, args, print_output=True, **kwargs):
    """The old way to call a server :
    - the server is called directly through ssh/rsh
    - reverse access to the client from the server is required to
      read the export file and other data files.
    """
    action = "serv"
    # read server informations
    serv = build_server_from_profile(prof, TYPES.EXEC)

    filename = get_absolute_path(prof.get_filename())
    if not serv.is_localhost():
        prof.from_remote_server()
        prof.WriteExportTo(filename)

    filename = "%s:%s" % (local_full_host, filename)
    if local_user != '':
        filename = "%s@%s" % (local_user, filename)

    cmd = [osp.join(serv.get_aster_root(), "bin",
                    get_plt_exec_name(prof.get_platform(), "as_run")), ]
    cmd.append("--" + action)
    cmd.append(filename)

    # for compatibility with old asrun server
    cmd.extend(magic.run.get_as_run_args())

    iret, output, err = serv.exec_command(cmd, display_forwarding=True)
    magic.run.DBG("******************** OUTPUT of as_run --%s ********************" % action, output,
            "******************** END of as_run --%s ********************" % action,
            all=True, prefix="    ")
    res = parse_submission_result(output)
    if print_output:
        print3("JOBID=%s QUEUE=%s STUDYID=%s" % res)
    return iret


def create_issue(prof, args, **kwargs):
    """Call --create_issue on a server."""
    # put the files on the server
    run = magic.run
    num_job = kwargs.get('num_job', run['num_job'])
    jobid = '%s-%s' % (num_job, "create_issue")
    # read server informations
    sexec = build_server_from_profile(prof, TYPES.EXEC)
    scopy = build_server_from_profile(prof, TYPES.COPY_TO, jobid=jobid)

    # read issue file
    issue_file = args[0]
    content = open(issue_file, 'r').read()
    dinf = parse_issue_file(content)
    scopy.copyto(issue_file)
    rfile = scopy.get_remote_filename(issue_file)

    # should we copy data files ?
    profname = "no_attachment"
    if dinf.get('FICASS') is not None:
        fprof = osp.join(run['tmp_user'], "%s.export" % jobid)
        iret, remote_prof = copy_datafiles_on_server(prof, jobid, fprof)
        profname = remote_prof.get_filename()
        if iret != 0:
            return iret

    targs = (None, rfile, profname)
    iret, output, err = call_generic_service("create_issue", sexec, prof, targs)
    scopy.delete_proxy_dir()
    return iret


def insert_in_db(prof, args, **kwargs):
    """Call --insert_in_db on a server."""
    run = magic.run
    num_job = kwargs.get('num_job', run['num_job'])
    jobid = '%s-%s' % (num_job, "insert_in_db")
    # read server informations
    sexec = build_server_from_profile(prof, TYPES.EXEC)
    scopy = build_server_from_profile(prof, TYPES.COPY_TO, jobid=jobid)

    # copy data files
    #XXX should result files be copied too ?
    #XXX should be run in foreground to keep display
    fprof = osp.join(run['tmp_user'], "%s.export" % jobid)
    iret, remote_prof = copy_datafiles_on_server(prof, jobid, fprof)
    if iret != 0:
        return iret

    targs = (None, remote_prof.get_filename(), )
    iret, output, err = call_generic_service("insert_in_db", sexec, prof, targs)
    scopy.delete_proxy_dir()
    return iret