예제 #1
0
def create_arc_job(job, configuration, logger):
    """Analog to create_job_script for ARC jobs:
    Creates symLinks for receiving result files, translates job dict to ARC
    xrsl, and stores resulting job script (xrsl + sh script) for submitting.
    
    We do _not_ create a separate job_dict with copies and SESSIONID inside,
    as opposed to create_job_script, all we need is the link from 
    webserver_home / sessionID into the user's home directory 
    ("job_output/job['JOB_ID']" is added to the result upload URLs in the 
    translation). 
    
    Returns message (ARC job ID if no error) and sessionid (None if error)
    """

    if not configuration.arc_clusters:
        return (None, "No ARC support!")
    if not job["JOBTYPE"] == "arc":
        return (None, "Error. This is not an ARC job")

    # Deep copy job for local changes
    job_dict = deepcopy(job)
    # Finally expand reserved job variables like +JOBID+ and +JOBNAME+
    job_dict = expand_variables(job_dict)
    # ... no more changes to job_dict from here on
    client_id = str(job_dict["USER_CERT"])

    # we do not want to see empty jobs here. Test as done in create_job_script.
    if client_id == configuration.empty_job_name:
        return (None, "Error. empty job for ARC?")

    # generate random session ID:
    sessionid = hexlify(open("/dev/urandom").read(32))
    logger.debug("session ID (for creating links): %s" % sessionid)

    client_dir = client_id_dir(client_id)

    # make symbolic links inside webserver_home:
    #
    # we need: link to owner's dir. to receive results,
    #          job mRSL inside sessid_to_mrsl_link_home
    linklist = [
        (configuration.user_home + client_dir, configuration.webserver_home + sessionid),
        (
            configuration.mrsl_files_dir + client_dir + "/" + str(job_dict["JOB_ID"]) + ".mRSL",
            configuration.sessid_to_mrsl_link_home + sessionid + ".mRSL",
        ),
    ]

    for (dest, loc) in linklist:
        make_symlink(dest, loc, logger)

    # the translation generates an xRSL object which specifies to execute
    # a shell script with script_name. If sessionid != None, results will
    # be uploaded to sid_redirect/sessionid/job_output/job_id

    try:
        (xrsl, script, script_name) = mrsltoxrsl.translate(job_dict, sessionid)
        logger.debug("translated to xRSL: %s" % xrsl)
        logger.debug("script:\n %s" % script)

    except Exception, err:
        # error during translation, pass a message
        logger.error("Error during xRSL translation: %s" % err.__str__())
        return (None, err.__str__())
예제 #2
0
def create_job_script(unique_resource_name, exe, job, resource_config, localjobname, configuration, logger):
    """Helper to create actual jobs for handout to a resource.

    Returns tuple with job dict on success and None otherwise.
    The job dict includes random generated sessionid and a I/O session id.
    """

    job_dict = {"": ""}
    sessionid = hexlify(open("/dev/urandom").read(32))
    iosessionid = hexlify(open("/dev/urandom").read(32))
    helper_dict_filename = os.path.join(
        configuration.resource_home, unique_resource_name, "empty_job_helper_dict.%s" % exe
    )

    # Deep copy job for local changes
    job_dict = deepcopy(job)

    job_dict["SESSIONID"] = sessionid
    job_dict["IOSESSIONID"] = iosessionid

    # Create ssh rsa keys and known_hosts for job mount

    mount_private_key = ""
    mount_public_key = ""
    mount_known_hosts = ""

    if job_dict.get("MOUNT", []) != []:

        # Generate public/private key pair for sshfs

        (mount_private_key, mount_public_key) = generate_ssh_rsa_key_pair()

        # Generate known_hosts

        if not os.path.exists(configuration.user_sftp_key_pub):
            msg = "job generation failed:"
            msg = "%s user_sftp_key_pub: '%s' -> File _NOT_ found" % (msg, configuration.user_sftp_key_pub)
            print msg
            logger.error(msg)
            return (None, msg)

        sftp_address = configuration.user_sftp_show_address
        sftp_addresses = socket.gethostbyname_ex(sftp_address or socket.getfqdn())
        sftp_port = configuration.user_sftp_show_port

        mount_known_hosts = "%s,[%s]:%s" % (sftp_addresses[0], sftp_addresses[0], sftp_port)
        for list_idx in xrange(1, len(sftp_addresses)):
            for sftp_address in sftp_addresses[list_idx]:
                mount_known_hosts += ",%s,[%s]:%s" % (sftp_address, sftp_address, sftp_port)

        fd = open(configuration.user_sftp_key_pub, "r")
        mount_known_hosts = "%s %s" % (mount_known_hosts, fd.read())
        fd.close()

    job_dict["MOUNTSSHPUBLICKEY"] = mount_public_key
    job_dict["MOUNTSSHPRIVATEKEY"] = mount_private_key
    job_dict["MOUNTSSHKNOWNHOSTS"] = mount_known_hosts

    if not job_dict.has_key("MAXPRICE"):
        job_dict["MAXPRICE"] = "0"
    # Finally expand reserved job variables like +JOBID+ and +JOBNAME+
    job_dict = expand_variables(job_dict)
    # ... no more changes to job_dict from here on
    client_id = str(job_dict["USER_CERT"])
    client_dir = client_id_dir(client_id)

    # if not job:

    if client_id == configuration.empty_job_name:

        # create link to empty job

        linkdest_empty_job = helper_dict_filename
        linkloc_empty_job = configuration.sessid_to_mrsl_link_home + sessionid + ".mRSL"
        make_symlink(linkdest_empty_job, linkloc_empty_job, logger)
    else:

        # link sessionid to mrsl file

        linkdest1 = configuration.mrsl_files_dir + client_dir + "/" + str(job_dict["JOB_ID"]) + ".mRSL"
        linkloc1 = configuration.sessid_to_mrsl_link_home + sessionid + ".mRSL"
        make_symlink(linkdest1, linkloc1, logger)

    # link sessionid to job owners home directory

    linkdest2 = configuration.user_home + client_dir
    linkloc2 = configuration.webserver_home + sessionid
    make_symlink(linkdest2, linkloc2, logger)

    # link iosessionid to job owners home directory

    linkdest3 = configuration.user_home + client_dir
    linkloc3 = configuration.webserver_home + iosessionid
    make_symlink(linkdest3, linkloc3, logger)

    # link sessionid to .job file

    linkdest4 = configuration.mig_system_files + str(job_dict["JOB_ID"]) + ".job"
    linkloc4 = configuration.webserver_home + sessionid + ".job"
    make_symlink(linkdest4, linkloc4, logger)

    # link sessionid to .getupdatefiles file

    linkdest5 = configuration.mig_system_files + str(job_dict["JOB_ID"]) + ".getupdatefiles"
    linkloc5 = configuration.webserver_home + sessionid + ".getupdatefiles"
    make_symlink(linkdest5, linkloc5, logger)

    # link sessionid to .sendoutputfiles file

    linkdest4 = configuration.mig_system_files + str(job_dict["JOB_ID"]) + ".sendoutputfiles"
    linkloc4 = configuration.webserver_home + sessionid + ".sendoutputfiles"
    make_symlink(linkdest4, linkloc4, logger)

    # link sessionid to .sendupdatefiles file

    linkdest5 = configuration.mig_system_files + str(job_dict["JOB_ID"]) + ".sendupdatefiles"
    linkloc5 = configuration.webserver_home + sessionid + ".sendupdatefiles"
    make_symlink(linkdest5, linkloc5, logger)

    path_without_extension = os.path.join(configuration.resource_home, unique_resource_name, localjobname)
    gen_res = gen_job_script(
        job_dict, resource_config, configuration, localjobname, path_without_extension, client_dir, exe, logger
    )
    if not gen_res:
        msg = "job scripts were not generated. Perhaps you have specified " + "an invalid SCRIPTLANGUAGE ? "
        print msg
        logger.error(msg)
        return (None, msg)

    inputfiles_path = path_without_extension + ".getinputfiles"

    # hack to ensure that a resource has a sandbox keyword

    if resource_config.get("SANDBOX", False):

        # Move file to webserver_home for download as we can't push it to
        # sandboxes

        try:

            # RA TODO: change download filename to something that
            # includes sessionid

            webserver_path = os.path.join(configuration.webserver_home, localjobname + ".getinputfiles")
            os.rename(inputfiles_path, webserver_path)

            # ########## ATTENTION HACK TO MAKE JVM SANDBOXES WORK ############
            # This should be changed to use the (to be developed) RE pre/post
            # processing framework. For now the user must have a jvm dir in his
            # home dir where the classfiles is located this should be changed
            # so that the execution homepath can be specified in the mRSL
            # jobfile
            # Martin Rehr 08/09/06

            # If this is a oneclick job link the users jvm dir to
            # webserver_home/sandboxkey.oneclick
            # This is done because the client applet uses the
            # codebase from which it is originaly loaded
            # Therefore the codebase must be dynamicaly changed
            # for every job

            if resource_config.has_key("PLATFORM") and resource_config["PLATFORM"] == "ONE-CLICK":

                # A two step link is made.
                # First sandboxkey.oneclick is made to point to
                # sessiondid.jvm
                # Second sessionid.jvm is set to point to
                # USER_HOME/jvm
                # This is done for security and easy cleanup,
                # sessionid.jvm is cleaned up
                # by the server upon job finish/timeout and
                # thereby leaving no open entryes to the users
                # jvm dir.

                linkintermediate = configuration.webserver_home + sessionid + ".jvm"

                if client_dir == configuration.empty_job_name:
                    linkdest = os.path.abspath(configuration.javabin_home)
                else:
                    linkdest = configuration.user_home + client_dir + os.sep + "jvm"

                # Make link sessionid.jvm -> USER_HOME/jvm

                make_symlink(linkdest, linkintermediate, logger)

                linkloc = configuration.webserver_home + resource_config["SANDBOXKEY"] + ".oneclick"

                # Remove previous symlink
                # This must be done in a try/catch as the symlink,
                # may be a dead link and 'if os.path.exists(linkloc):'
                # will then return false, even though the link exists.

                try:
                    os.remove(linkloc)
                except:
                    pass

                # Make link sandboxkey.oneclick -> sessionid.jvm

                make_symlink(linkintermediate, linkloc, logger)
        except Exception, err:

            # ######### End JVM SANDBOX HACK ###########

            msg = "File '%s' was not copied to the webserver home." % inputfiles_path
            print "\nERROR: " + str(err)
            logger.error(msg)
            return (None, msg)

        return (job_dict, "OK")
예제 #3
0
def create_arc_job(
    job,
    configuration,
    logger,
):
    """Analog to create_job_script for ARC jobs:
    Creates symLinks for receiving result files, translates job dict to ARC
    xrsl, and stores resulting job script (xrsl + sh script) for submitting.

    We do _not_ create a separate job_dict with copies and SESSIONID inside,
    as opposed to create_job_script, all we need is the link from 
    webserver_home / sessionID into the user's home directory 
    ("job_output/job['JOB_ID']" is added to the result upload URLs in the 
    translation). 

    Returns message (ARC job ID if no error) and sessionid (None if error)
    """

    if not configuration.arc_clusters:
        return (None, 'No ARC support!')
    if not job['JOBTYPE'] == 'arc':
        return (None, 'Error. This is not an ARC job')

    # Deep copy job for local changes
    job_dict = deepcopy(job)
    # Finally expand reserved job variables like +JOBID+ and +JOBNAME+
    job_dict = expand_variables(job_dict)
    # ... no more changes to job_dict from here on
    client_id = str(job_dict['USER_CERT'])

    # we do not want to see empty jobs here. Test as done in create_job_script.
    if client_id == configuration.empty_job_name:
        return (None, 'Error. empty job for ARC?')

    # generate random session ID:
    sessionid = hexlify(open('/dev/urandom').read(session_id_bytes))
    logger.debug('session ID (for creating links): %s' % sessionid)

    client_dir = client_id_dir(client_id)

    # make symbolic links inside webserver_home:
    #
    # we need: link to owner's dir. to receive results,
    #          job mRSL inside sessid_to_mrsl_link_home
    linklist = [(configuration.user_home + client_dir,
                 configuration.webserver_home + sessionid),
                (configuration.mrsl_files_dir + client_dir + '/' +
                 str(job_dict['JOB_ID']) + '.mRSL',
                 configuration.sessid_to_mrsl_link_home + sessionid + '.mRSL')
                ]

    for (dest, loc) in linklist:
        make_symlink(dest, loc, logger)

    # the translation generates an xRSL object which specifies to execute
    # a shell script with script_name. If sessionid != None, results will
    # be uploaded to sid_redirect/sessionid/job_output/job_id

    try:
        (xrsl, script, script_name) = mrsltoxrsl.translate(job_dict, sessionid)
        logger.debug('translated to xRSL: %s' % xrsl)
        logger.debug('script:\n %s' % script)

    except Exception, err:
        # error during translation, pass a message
        logger.error('Error during xRSL translation: %s' % err.__str__())
        return (None, err.__str__())
예제 #4
0
def create_job_script(
    unique_resource_name,
    exe,
    job,
    resource_config,
    localjobname,
    configuration,
    logger,
):
    """Helper to create actual jobs for handout to a resource.

    Returns tuple with job dict on success and None otherwise.
    The job dict includes random generated sessionid and a I/O session id.
    """

    job_dict = {'': ''}
    # TODO: hexlify is an awfully space wasting URL-safe encoding.
    #       We should just use something like the proposed secure method from
    #       http://stackoverflow.com/a/23728630/2213647
    sessionid = hexlify(open('/dev/urandom').read(session_id_bytes))
    iosessionid = hexlify(open('/dev/urandom').read(session_id_bytes))
    helper_dict_filename = os.path.join(configuration.resource_home,
                                        unique_resource_name,
                                        'empty_job_helper_dict.%s' % exe)

    # Deep copy job for local changes
    job_dict = deepcopy(job)
    # Bump requested values to any resource specs requested in MAXFILL
    job_maxfill = job_dict.get('MAXFILL', [])
    if keyword_all in job_maxfill:
        job_maxfill = maxfill_fields
    for name in maxfill_fields:
        if name in job_maxfill:
            job_dict[name] = resource_config[name]

    job_dict['SESSIONID'] = sessionid
    job_dict['IOSESSIONID'] = iosessionid

    # Create ssh rsa keys and known_hosts for job mount

    mount_private_key = ""
    mount_public_key = ""
    mount_known_hosts = ""

    if job_dict.get('MOUNT', []) != []:

        # Generate public/private key pair for sshfs

        (mount_private_key, mount_public_key) = generate_ssh_rsa_key_pair()

        # Generate known_hosts

        if not os.path.exists(configuration.user_sftp_key_pub):
            msg = "job generation failed:"
            msg = "%s user_sftp_key_pub: '%s' -> File NOT found" % \
                  (msg, configuration.user_sftp_key_pub)
            print msg
            logger.error(msg)
            return (None, msg)

        # Use best available sftp implementation - configuration picks it
        sftp_address = configuration.user_sftp_show_address
        sftp_port = configuration.user_sftp_show_port
        sftp_addresses = socket.gethostbyname_ex(sftp_address or
                                                 socket.getfqdn())
        mount_known_hosts = "%s,[%s]:%s" % (sftp_addresses[0],
                                            sftp_addresses[0], sftp_port)
        for list_idx in xrange(1, len(sftp_addresses)):
            for sftp_address in sftp_addresses[list_idx]:
                mount_known_hosts += ",%s,[%s]:%s" % (sftp_address,
                                                      sftp_address,
                                                      sftp_port)

        fd = open(configuration.user_sftp_key_pub, 'r')
        mount_known_hosts = "%s %s" % (mount_known_hosts, fd.read())
        fd.close()

    job_dict['MOUNTSSHPUBLICKEY'] = mount_public_key
    job_dict['MOUNTSSHPRIVATEKEY'] = mount_private_key
    job_dict['MOUNTSSHKNOWNHOSTS'] = mount_known_hosts

    if not job_dict.has_key('MAXPRICE'):
        job_dict['MAXPRICE'] = '0'
    # Finally expand reserved job variables like +JOBID+ and +JOBNAME+
    job_dict = expand_variables(job_dict)
    # ... no more changes to job_dict from here on
    client_id = str(job_dict['USER_CERT'])
    client_dir = client_id_dir(client_id)

    # if not job:

    if client_id == configuration.empty_job_name:

        # create link to empty job

        linkdest_empty_job = helper_dict_filename
        linkloc_empty_job = configuration.sessid_to_mrsl_link_home + \
            sessionid + '.mRSL'
        make_symlink(linkdest_empty_job, linkloc_empty_job, logger)
    else:

        # link sessionid to mrsl file

        linkdest1 = configuration.mrsl_files_dir + client_dir + '/' + \
            str(job_dict['JOB_ID']) + '.mRSL'
        linkloc1 = configuration.sessid_to_mrsl_link_home + sessionid + '.mRSL'
        make_symlink(linkdest1, linkloc1, logger)

    # link sessionid to job owners home directory

    linkdest2 = configuration.user_home + client_dir
    linkloc2 = configuration.webserver_home + sessionid
    make_symlink(linkdest2, linkloc2, logger)

    # link iosessionid to job owners home directory

    linkdest3 = configuration.user_home + client_dir
    linkloc3 = configuration.webserver_home + iosessionid
    make_symlink(linkdest3, linkloc3, logger)

    # link sessionid to .job file

    linkdest4 = configuration.mig_system_files + str(job_dict['JOB_ID']) + \
        '.job'
    linkloc4 = configuration.webserver_home + sessionid + '.job'
    make_symlink(linkdest4, linkloc4, logger)

    # link sessionid to .getupdatefiles file

    linkdest5 = configuration.mig_system_files + str(job_dict['JOB_ID']) + \
        '.getupdatefiles'
    linkloc5 = configuration.webserver_home + sessionid + \
        '.getupdatefiles'
    make_symlink(linkdest5, linkloc5, logger)

    # link sessionid to .sendoutputfiles file

    linkdest4 = configuration.mig_system_files + str(job_dict['JOB_ID']) + \
        '.sendoutputfiles'
    linkloc4 = configuration.webserver_home + sessionid + \
        '.sendoutputfiles'
    make_symlink(linkdest4, linkloc4, logger)

    # link sessionid to .sendupdatefiles file

    linkdest5 = configuration.mig_system_files + str(job_dict['JOB_ID']) + \
        '.sendupdatefiles'
    linkloc5 = configuration.webserver_home + sessionid + \
        '.sendupdatefiles'
    make_symlink(linkdest5, linkloc5, logger)

    path_without_extension = os.path.join(configuration.resource_home,
                                          unique_resource_name, localjobname)
    gen_res = gen_job_script(
        job_dict,
        resource_config,
        configuration,
        localjobname,
        path_without_extension,
        client_dir,
        exe,
        logger,
    )
    if not gen_res:
        msg = \
            'job scripts were not generated. Perhaps you have specified ' + \
            'an invalid SCRIPTLANGUAGE ? '
        print msg
        logger.error(msg)
        return (None, msg)

    inputfiles_path = path_without_extension + '.getinputfiles'

    # hack to ensure that a resource has a sandbox keyword

    if resource_config.get('SANDBOX', False):

        # Move file to webserver_home for download as we can't push it to
        # sandboxes

        try:

            # RA TODO: change download filename to something that
            # includes sessionid

            webserver_path = os.path.join(configuration.webserver_home,
                                          localjobname + '.getinputfiles')
            os.rename(inputfiles_path, webserver_path)

            # ########## ATTENTION HACK TO MAKE JVM SANDBOXES WORK ############
            # This should be changed to use the (to be developed) RE pre/post
            # processing framework. For now the user must have a jvm dir in his
            # home dir where the classfiles is located this should be changed
            # so that the execution homepath can be specified in the mRSL
            # jobfile
            # Martin Rehr 08/09/06

            # If this is a oneclick job link the users jvm dir to
            # webserver_home/sandboxkey.oneclick
            # This is done because the client applet uses the
            # codebase from which it is originaly loaded
            # Therefore the codebase must be dynamicaly changed
            # for every job

            if resource_config.has_key('PLATFORM') and \
                    resource_config['PLATFORM'] == 'ONE-CLICK':

                # A two step link is made.
                # First sandboxkey.oneclick is made to point to
                # sessiondid.jvm
                # Second sessionid.jvm is set to point to
                # USER_HOME/jvm
                # This is done for security and easy cleanup,
                # sessionid.jvm is cleaned up
                # by the server upon job finish/timeout and
                # thereby leaving no open entryes to the users
                # jvm dir.

                linkintermediate = configuration.webserver_home + \
                    sessionid + '.jvm'

                if client_dir == configuration.empty_job_name:
                    linkdest = os.path.abspath(configuration.javabin_home)
                else:
                    linkdest = configuration.user_home + client_dir + \
                        os.sep + 'jvm'

                # Make link sessionid.jvm -> USER_HOME/jvm

                make_symlink(linkdest, linkintermediate, logger)

                linkloc = configuration.webserver_home + \
                    resource_config['SANDBOXKEY'] + '.oneclick'

                # Remove previous symlink
                # This must be done in a try/catch as the symlink,
                # may be a dead link and 'if os.path.exists(linkloc):'
                # will then return false, even though the link exists.

                try:
                    os.remove(linkloc)
                except:
                    pass

                # Make link sandboxkey.oneclick -> sessionid.jvm

                make_symlink(linkintermediate, linkloc, logger)
        except Exception, err:

                # ######### End JVM SANDBOX HACK ###########

            msg = "File '%s' was not copied to the webserver home." % \
                  inputfiles_path
            print '\nERROR: ' + str(err)
            logger.error(msg)
            return (None, msg)

        return (job_dict, 'OK')
예제 #5
0
파일: jobstatus.py 프로젝트: ucphhpc/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    client_dir = client_id_dir(client_id)
    status = returnvalues.OK
    defaults = signature()[1]
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
    )
    if not validate_status:
        logger.error("jobstatus input validation failed: %s" % accepted)
        return (accepted, returnvalues.CLIENT_ERROR)

    flags = ''.join(accepted['flags'])
    max_jobs = int(accepted['max_jobs'][-1])
    order = 'unsorted '
    if sorted(flags):
        order = 'sorted '
    patterns = accepted['job_id']
    project_names = accepted['project_name']

    if len(project_names) > 0:
        for project_name in project_names:
            project_name_job_ids = \
                get_job_ids_with_specified_project_name(client_id,
                    project_name, configuration.mrsl_files_dir, logger)
            patterns.extend(project_name_job_ids)

    if not configuration.site_enable_jobs:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''Job execution is not enabled on this system'''
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # Please note that base_dir must end in slash to avoid access to other
    # user dirs when own name is a prefix of another user name

    base_dir = \
        os.path.abspath(os.path.join(configuration.mrsl_files_dir,
                        client_dir)) + os.sep

    output_objects.append({'object_type': 'header', 'text'
                          : '%s %s job status' % \
                            (configuration.short_title, order)})

    if not patterns:
        output_objects.append({
            'object_type': 'error_text',
            'text': 'No job_id specified!'
        })
        return (output_objects, returnvalues.NO_SUCH_JOB_ID)

    if verbose(flags):
        for flag in flags:
            output_objects.append({
                'object_type': 'text',
                'text': '%s using flag: %s' % (op_name, flag)
            })

    if not os.path.isdir(base_dir):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : ('You have not been created as a user on the %s server! ' \
                'Please contact the %s team.') % \
             (configuration.short_title, configuration.short_title)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    filelist = []
    for pattern in patterns:
        pattern = pattern.strip()

        # Backward compatibility - all_jobs keyword should match all jobs

        if pattern == all_jobs:
            pattern = '*'

        # Check directory traversal attempts before actual handling to
        # avoid leaking information about file system layout while
        # allowing consistent error messages

        unfiltered_match = glob.glob(base_dir + pattern + '.mRSL')
        match = []
        for server_path in unfiltered_match:
            # IMPORTANT: path must be expanded to abs for proper chrooting
            abs_path = os.path.abspath(server_path)
            if not valid_user_path(configuration, abs_path, base_dir, True):

                # out of bounds - save user warning for later to allow
                # partial match:
                # ../*/* is technically allowed to match own files.

                logger.warning('%s tried to %s restricted path %s ! (%s)' %
                               (client_id, op_name, abs_path, pattern))
                continue

            # Insert valid job files in filelist for later treatment

            match.append(abs_path)

        # Now actually treat list of allowed matchings and notify if no
        # (allowed) match....

        if not match:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                '%s: You do not have any matching job IDs!' % pattern
            })
            status = returnvalues.CLIENT_ERROR
        else:
            filelist += match

    if sorted(flags):
        sort(filelist)

    if max_jobs > 0 and max_jobs < len(filelist):
        output_objects.append({
            'object_type':
            'text',
            'text':
            'Only showing first %d of the %d matching jobs as requested' %
            (max_jobs, len(filelist))
        })
        filelist = filelist[:max_jobs]

    # Iterate through jobs and list details for each

    job_list = {'object_type': 'job_list', 'jobs': []}

    for filepath in filelist:

        # Extract job_id from filepath (replace doesn't modify filepath)

        mrsl_file = filepath.replace(base_dir, '')
        job_id = mrsl_file.replace('.mRSL', '')
        job_dict = unpickle(filepath, logger)
        if not job_dict:
            status = returnvalues.CLIENT_ERROR

            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : 'No such job: %s (could not load mRSL file %s)' % \
                 (job_id, filepath)})
            continue

        # Expand any job variables before use
        job_dict = expand_variables(job_dict)

        job_obj = {'object_type': 'job', 'job_id': job_id}
        job_obj['status'] = job_dict['STATUS']

        time_fields = [
            'VERIFIED',
            'VERIFIED_TIMESTAMP',
            'RECEIVED_TIMESTAMP',
            'QUEUED_TIMESTAMP',
            'SCHEDULE_TIMESTAMP',
            'EXECUTING_TIMESTAMP',
            'FINISHED_TIMESTAMP',
            'FAILED_TIMESTAMP',
            'CANCELED_TIMESTAMP',
        ]
        for name in time_fields:
            if job_dict.has_key(name):

                # time objects cannot be marshalled, asctime if timestamp

                try:
                    job_obj[name.lower()] = time.asctime(job_dict[name])
                except Exception, exc:

                    # not a time object, just add

                    job_obj[name.lower()] = job_dict[name]

        ###########################################
        # ARC job status retrieval on demand:
        # But we should _not_ update the status in the mRSL files, since
        # other MiG code might rely on finding only valid "MiG" states.

        if configuration.arc_clusters and \
               job_dict.get('UNIQUE_RESOURCE_NAME', 'unset') == 'ARC' \
               and job_dict['STATUS'] == 'EXECUTING':
            try:
                home = os.path.join(configuration.user_home, client_dir)
                arcsession = arc.Ui(home)
                arcstatus = arcsession.jobStatus(job_dict['EXE'])
                job_obj['status'] = arcstatus['status']
            except arc.ARCWrapperError, err:
                logger.error('Error retrieving ARC job status: %s' % \
                             err.what())
                job_obj['status'] += '(Error: ' + err.what() + ')'
            except arc.NoProxyError, err:
                logger.error('While retrieving ARC job status: %s' % \
                             err.what())
                job_obj['status'] += '(Error: ' + err.what() + ')'
예제 #6
0
파일: jobstatus.py 프로젝트: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    client_dir = client_id_dir(client_id)
    status = returnvalues.OK
    defaults = signature()[1]
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
        )
    if not validate_status:
        logger.error("jobstatus input validation failed: %s" % accepted)
        return (accepted, returnvalues.CLIENT_ERROR)

    flags = ''.join(accepted['flags'])
    max_jobs = int(accepted['max_jobs'][-1])
    order = 'unsorted '
    if sorted(flags):
        order = 'sorted '
    patterns = accepted['job_id']
    project_names = accepted['project_name']

    if len(project_names) > 0:
        for project_name in project_names:
            project_name_job_ids = \
                get_job_ids_with_specified_project_name(client_id,
                    project_name, configuration.mrsl_files_dir, logger)
            patterns.extend(project_name_job_ids)

    # Please note that base_dir must end in slash to avoid access to other
    # user dirs when own name is a prefix of another user name

    base_dir = \
        os.path.abspath(os.path.join(configuration.mrsl_files_dir,
                        client_dir)) + os.sep

    output_objects.append({'object_type': 'header', 'text'
                          : '%s %s job status' % \
                            (configuration.short_title, order)})

    if not patterns:
        output_objects.append({'object_type': 'error_text', 'text'
                               : 'No job_id specified!'})
        return (output_objects, returnvalues.NO_SUCH_JOB_ID)

    if verbose(flags):
        for flag in flags:
            output_objects.append({'object_type': 'text', 'text'
                                  : '%s using flag: %s' % (op_name,
                                  flag)})

    if not os.path.isdir(base_dir):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : ('You have not been created as a user on the %s server! ' \
                'Please contact the %s team.') % \
             (configuration.short_title, configuration.short_title)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    filelist = []
    for pattern in patterns:
        pattern = pattern.strip()

        # Backward compatibility - all_jobs keyword should match all jobs

        if pattern == all_jobs:
            pattern = '*'

        # Check directory traversal attempts before actual handling to
        # avoid leaking information about file system layout while
        # allowing consistent error messages

        unfiltered_match = glob.glob(base_dir + pattern + '.mRSL')
        match = []
        for server_path in unfiltered_match:
            real_path = os.path.abspath(server_path)
            if not valid_user_path(real_path, base_dir, True):

                # out of bounds - save user warning for later to allow
                # partial match:
                # ../*/* is technically allowed to match own files.

                logger.warning('%s tried to %s restricted path %s ! (%s)'
                               % (client_id, op_name, real_path, pattern))
                continue

            # Insert valid job files in filelist for later treatment

            match.append(real_path)

        # Now actually treat list of allowed matchings and notify if no
        # (allowed) match....

        if not match:
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : '%s: You do not have any matching job IDs!' % pattern})
            status = returnvalues.CLIENT_ERROR
        else:
            filelist += match

    if sorted(flags):
        sort(filelist)

    if max_jobs < len(filelist):
        output_objects.append(
            {'object_type': 'text', 'text'
             : 'Only showing first %d of the %d matching jobs as requested'
             % (max_jobs, len(filelist))})
        filelist = filelist[:max_jobs]

    # Iterate through jobs and print details for each

    job_list = {'object_type': 'job_list', 'jobs': []}

    for filepath in filelist:

        # Extract job_id from filepath (replace doesn't modify filepath)

        mrsl_file = filepath.replace(base_dir, '')
        job_id = mrsl_file.replace('.mRSL', '')
        job_dict = unpickle(filepath, logger)
        if not job_dict:
            status = returnvalues.CLIENT_ERROR

            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : 'No such job: %s (could not load mRSL file %s)' % \
                 (job_id, filepath)})
            continue

        # Expand any job variables before use
        job_dict = expand_variables(job_dict)

        job_obj = {'object_type': 'job', 'job_id': job_id}
        job_obj['status'] = job_dict['STATUS']

        time_fields = [
            'VERIFIED',
            'VERIFIED_TIMESTAMP',
            'RECEIVED_TIMESTAMP',
            'QUEUED_TIMESTAMP',
            'SCHEDULE_TIMESTAMP',
            'EXECUTING_TIMESTAMP',
            'FINISHED_TIMESTAMP',
            'FAILED_TIMESTAMP',
            'CANCELED_TIMESTAMP',
            ]
        for name in time_fields:
            if job_dict.has_key(name):

                # time objects cannot be marshalled, asctime if timestamp

                try:
                    job_obj[name.lower()] = time.asctime(job_dict[name])
                except Exception, exc:

                    # not a time object, just add

                    job_obj[name.lower()] = job_dict[name]

        ###########################################
        # ARC job status retrieval on demand:
        # But we should _not_ update the status in the mRSL files, since 
        # other MiG code might rely on finding only valid "MiG" states.
        
        if configuration.arc_clusters and \
               job_dict.get('UNIQUE_RESOURCE_NAME', 'unset') == 'ARC' \
               and job_dict['STATUS'] == 'EXECUTING':
            try:
                home = os.path.join(configuration.user_home, client_dir)
                arcsession = arc.Ui(home)
                arcstatus = arcsession.jobStatus(job_dict['EXE'])
                job_obj['status'] = arcstatus['status']
            except arc.ARCWrapperError, err:
                logger.error('Error retrieving ARC job status: %s' % \
                             err.what())
                job_obj['status'] += '(Error: ' + err.what() + ')' 
            except arc.NoProxyError, err:
                logger.error('While retrieving ARC job status: %s' % \
                             err.what())
                job_obj['status'] += '(Error: ' + err.what() + ')'