Example #1
0
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)
    defaults = signature()[1]
    title_entry = find_entry(output_objects, 'title')
    label = "%s" % configuration.site_vgrid_label
    title_entry['text'] = '%s send request' % configuration.short_title
    output_objects.append({
        'object_type': 'header',
        'text': '%s send request' % configuration.short_title
    })
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
    )
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    target_id = client_id
    vgrid_name = accepted['vgrid_name'][-1].strip()
    visible_user_names = accepted['cert_id']
    visible_res_names = accepted['unique_resource_name']
    request_type = accepted['request_type'][-1].strip().lower()
    request_text = accepted['request_text'][-1].strip()
    protocols = [proto.strip() for proto in accepted['protocol']]
    use_any = False
    if any_protocol in protocols:
        use_any = True
        protocols = configuration.notify_protocols
    protocols = [proto.lower() for proto in protocols]

    if not safe_handler(configuration, 'post', op_name, client_id,
                        get_csrf_limit(configuration), accepted):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''Only accepting
CSRF-filtered POST requests to prevent unintended updates'''
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    valid_request_types = [
        'resourceowner', 'resourceaccept', 'resourcereject', 'vgridowner',
        'vgridmember', 'vgridresource', 'vgridaccept', 'vgridreject', 'plain'
    ]
    if not request_type in valid_request_types:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '%s is not a valid request_type (valid types: %s)!' %
            (request_type.lower(), valid_request_types)
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    if not protocols:
        output_objects.append({
            'object_type': 'error_text',
            'text': 'No protocol specified!'
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    user_map = get_user_map(configuration)
    reply_to = user_map[client_id][USERID]
    # Try to point replies to client_id email
    client_email = extract_field(reply_to, 'email')

    if request_type == "plain":
        if not visible_user_names:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No user ID specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        user_id = visible_user_names[-1].strip()
        anon_map = anon_to_real_user_map(configuration)
        if anon_map.has_key(user_id):
            user_id = anon_map[user_id]
        if not user_map.has_key(user_id):
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No such user: %s' % user_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_name = user_id
        user_dict = user_map[user_id]
        vgrid_access = user_vgrid_access(configuration, client_id)
        vgrids_allow_email = user_dict[CONF].get('VGRIDS_ALLOW_EMAIL', [])
        vgrids_allow_im = user_dict[CONF].get('VGRIDS_ALLOW_IM', [])
        if any_vgrid in vgrids_allow_email:
            email_vgrids = vgrid_access
        else:
            email_vgrids = set(vgrids_allow_email).intersection(vgrid_access)
        if any_vgrid in vgrids_allow_im:
            im_vgrids = vgrid_access
        else:
            im_vgrids = set(vgrids_allow_im).intersection(vgrid_access)
        if use_any:
            # Do not try disabled protocols if ANY was requested
            if not email_vgrids:
                protocols = [
                    proto for proto in protocols
                    if proto not in email_keyword_list
                ]
            if not im_vgrids:
                protocols = [
                    proto for proto in protocols if proto in email_keyword_list
                ]
        if not email_vgrids and [
                proto for proto in protocols if proto in email_keyword_list
        ]:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You are not allowed to send emails to %s!' % user_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not im_vgrids and [
                proto for proto in protocols if proto not in email_keyword_list
        ]:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You are not allowed to send instant messages to %s!' % user_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        for proto in protocols:
            if not user_dict[CONF].get(proto.upper(), False):
                if use_any:
                    # Remove missing protocols if ANY protocol was requested
                    protocols = [i for i in protocols if i != proto]
                else:
                    output_objects.append({
                        'object_type':
                        'error_text',
                        'text':
                        'User %s does not accept %s messages!' %
                        (user_id, proto)
                    })
                    return (output_objects, returnvalues.CLIENT_ERROR)
        if not protocols:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'User %s does not accept requested protocol(s) messages!' %
                user_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_list = [user_id]
    elif request_type in ["vgridaccept", "vgridreject"]:
        # Always allow accept messages but only between owners/members
        if not visible_user_names and not visible_res_names:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No user or resource ID specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not vgrid_name:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No vgrid_name specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if vgrid_name.upper() == default_vgrid.upper():
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'No requests for %s are allowed!' % default_vgrid
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not vgrid_is_owner(vgrid_name, client_id, configuration):
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You are not an owner of %s or a parent %s!' %
                (vgrid_name, label)
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        # NOTE: we support exactly one vgrid but multiple users/resources here
        if visible_user_names:
            logger.info("setting user recipients: %s" % visible_user_names)
            target_list = [user_id.strip() for user_id in visible_user_names]
        elif visible_res_names:
            # vgrid resource accept - lookup and notify resource owners
            logger.info("setting res owner recipients: %s" % visible_res_names)
            target_list = []
            for unique_resource_name in visible_res_names:
                logger.info("loading res owners for %s" % unique_resource_name)
                (load_status,
                 res_owners) = resource_owners(configuration,
                                               unique_resource_name)
                if not load_status:
                    output_objects.append({
                        'object_type':
                        'error_text',
                        'text':
                        'Could not lookup owners of %s!' % unique_resource_name
                    })
                    continue
                logger.info("adding res owners to recipients: %s" % res_owners)
                target_list += [user_id for user_id in res_owners]

        target_id = '%s %s owners' % (vgrid_name, label)
        target_name = vgrid_name
    elif request_type in ["resourceaccept", "resourcereject"]:
        # Always allow accept messages between actual resource owners
        if not visible_user_names:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No user ID specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not visible_res_names:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No resource ID specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        # NOTE: we support exactly one resource but multiple users here
        unique_resource_name = visible_res_names[-1].strip()
        target_name = unique_resource_name
        res_map = get_resource_map(configuration)
        if not res_map.has_key(unique_resource_name):
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'No such resource: %s' % unique_resource_name
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        owners_list = res_map[unique_resource_name][OWNERS]
        if not client_id in owners_list:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You are not an owner of %s!' % unique_resource_name
            })
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Invalid resource %s message!' % request_type
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_id = '%s resource owners' % unique_resource_name
        target_name = unique_resource_name
        target_list = [user_id.strip() for user_id in visible_user_names]
    elif request_type == "resourceowner":
        if not visible_res_names:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No resource ID specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        # NOTE: we support exactly one resource but multiple users here
        unique_resource_name = visible_res_names[-1].strip()
        anon_map = anon_to_real_res_map(configuration.resource_home)
        if anon_map.has_key(unique_resource_name):
            unique_resource_name = anon_map[unique_resource_name]
        target_name = unique_resource_name
        res_map = get_resource_map(configuration)
        if not res_map.has_key(unique_resource_name):
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'No such resource: %s' % unique_resource_name
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_list = res_map[unique_resource_name][OWNERS]
        if client_id in target_list:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You are already an owner of %s!' % unique_resource_name
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        request_dir = os.path.join(configuration.resource_home,
                                   unique_resource_name)
        access_request = {
            'request_type': request_type,
            'entity': client_id,
            'target': unique_resource_name,
            'request_text': request_text
        }
        if not save_access_request(configuration, request_dir, access_request):
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Could not save request - owners may still manually add you'
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)
    elif request_type in ["vgridmember", "vgridowner", "vgridresource"]:
        if not vgrid_name:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No vgrid_name specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        # default vgrid is read-only

        if vgrid_name.upper() == default_vgrid.upper():
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'No requests for %s are not allowed!' % default_vgrid
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        # stop owner or member request if already an owner
        # and prevent repeated resource access requests

        if request_type == 'vgridresource':
            # NOTE: we support exactly one resource here
            unique_resource_name = visible_res_names[-1].strip()
            target_id = entity = unique_resource_name
            if vgrid_is_resource(vgrid_name, unique_resource_name,
                                 configuration):
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'You already have access to %s or a parent %s.' %
                    (vgrid_name, label)
                })
                return (output_objects, returnvalues.CLIENT_ERROR)
        else:
            target_id = entity = client_id
            if vgrid_is_owner(vgrid_name, client_id, configuration):
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'You are already an owner of %s or a parent %s!' %
                    (vgrid_name, label)
                })
                return (output_objects, returnvalues.CLIENT_ERROR)

        # only ownership requests are allowed for existing members

        if request_type == 'vgridmember':
            if vgrid_is_member(vgrid_name, client_id, configuration):
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'You are already a member of %s or a parent %s.' %
                    (vgrid_name, label)
                })
                return (output_objects, returnvalues.CLIENT_ERROR)

        # Find all VGrid owners configured to receive notifications

        target_name = vgrid_name
        (settings_status, settings_dict) = vgrid_settings(vgrid_name,
                                                          configuration,
                                                          recursive=True,
                                                          as_dict=True)
        if not settings_status:
            settings_dict = {}
        request_recipients = settings_dict.get('request_recipients',
                                               default_vgrid_settings_limit)
        # We load and use direct owners first if any - otherwise inherited
        owners_list = []
        for inherited in (False, True):
            (owners_status, owners_list) = vgrid_owners(vgrid_name,
                                                        configuration,
                                                        recursive=inherited)
            if not owners_status:
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'Failed to lookup owners for %s %s - sure it exists?' %
                    (vgrid_name, label)
                })
                return (output_objects, returnvalues.CLIENT_ERROR)
            elif owners_list:
                break
        if not owners_list:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Failed to lookup owners for %s %s - sure it exists?' %
                (vgrid_name, label)
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        # Now we have direct or inherited owners to notify
        target_list = owners_list[:request_recipients]

        request_dir = os.path.join(configuration.vgrid_home, vgrid_name)
        access_request = {
            'request_type': request_type,
            'entity': entity,
            'target': vgrid_name,
            'request_text': request_text
        }
        if not save_access_request(configuration, request_dir, access_request):
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Could not save request - owners may still manually add you'
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)

    else:
        output_objects.append({
            'object_type': 'error_text',
            'text': 'Invalid request type: %s' % request_type
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Now send request to all targets in turn
    # TODO: inform requestor if no owners have mail/IM set in their settings

    logger.debug("sending notification to recipients: %s" % target_list)

    for target in target_list:

        if not target:
            logger.warning("skipping empty notify target: %s" % target_list)
            continue

        # USER_CERT entry is destination

        notify = []
        for proto in protocols:
            notify.append('%s: SETTINGS' % proto)
        job_dict = {
            'NOTIFY': notify,
            'JOB_ID': 'NOJOBID',
            'USER_CERT': target,
            'EMAIL_SENDER': client_email
        }

        notifier = notify_user_thread(
            job_dict,
            [target_id, target_name, request_type, request_text, reply_to],
            'SENDREQUEST',
            logger,
            '',
            configuration,
        )

        # Try finishing delivery but do not block forever on one message
        notifier.join(30)
    output_objects.append({
        'object_type':
        'text',
        'text':
        'Sent %s message to %d people' % (request_type, len(target_list))
    })
    output_objects.append({
        'object_type':
        'text',
        'text':
        """Please make sure you have notifications
configured on your Setings page if you expect a reply to this message"""
    })

    return (output_objects, returnvalues.OK)
Example #2
0
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)
    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:
        return (accepted, returnvalues.CLIENT_ERROR)

    unique_res_names = accepted["unique_resource_name"]

    (re_stat, re_list) = list_runtime_environments(configuration)
    if not re_stat:
        logger.warning("Failed to load list of runtime environments")
        output_objects.append({"object_type": "error_text", "text": "Error getting list of runtime environments"})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    title_entry = find_entry(output_objects, "title")
    title_entry["text"] = "Resource Management"
    title_entry["style"] = themed_styles(configuration)
    title_entry[
        "javascript"
    ] = """
<script type="text/javascript" src="/images/js/jquery.js"></script>
<script type="text/javascript" src="/images/js/jquery-ui.js"></script>
<script type="text/javascript" src="/images/js/jquery.confirm.js"></script>

<script type="text/javascript" >
var toggleHidden = function(classname) {
    // classname supposed to have a leading dot 
        $(classname).toggleClass("hidden");
    }
    
$(document).ready(function() {

          // init confirmation dialog
          $("#confirm_dialog").dialog(
              // see http://jqueryui.com/docs/dialog/ for options
              { autoOpen: false,
                modal: true, closeOnEscape: true,
                width: 500,
                buttons: {
                   "Cancel": function() { $("#" + name).dialog("close"); }
	        }
              });
     }
);
</script>
"""
    output_objects.append({"object_type": "header", "text": " Resource Management"})

    output_objects.append({"object_type": "sectionheader", "text": "%s Resources Owned" % configuration.short_title})
    quick_links = [{"object_type": "text", "text": "Quick links to all your resources and individual management"}]
    quick_links.append({"object_type": "html_form", "text": '<div class="hidden quicklinks">'})
    quick_links.append(
        {
            "object_type": "link",
            "destination": "javascript:toggleHidden('.quicklinks');",
            "class": "removeitemlink",
            "title": "Toggle view",
            "text": "Hide quick links",
        }
    )
    quick_links.append({"object_type": "text", "text": ""})

    quick_res = {}
    quick_links_index = len(output_objects)
    output_objects.append({"object_type": "sectionheader", "text": ""})

    output_objects.append(
        {
            "object_type": "html_form",
            "text": """
 <div id="confirm_dialog" title="Confirm" style="background:#fff;">
  <div id="confirm_text"><!-- filled by js --></div>
   <textarea cols="40" rows="4" id="confirm_input" style="display:none;"></textarea>
 </div>
""",
        }
    )

    owned = 0
    res_map = get_resource_map(configuration)
    for unique_resource_name in res_map.keys():
        if sandbox_resource(unique_resource_name):
            continue
        owner_list = res_map[unique_resource_name][OWNERS]
        resource_config = res_map[unique_resource_name][CONF]
        visible_res_name = res_map[unique_resource_name][RESID]
        if client_id in owner_list:
            quick_res[unique_resource_name] = {
                "object_type": "multilinkline",
                "links": [
                    {
                        "object_type": "link",
                        "destination": "?unique_resource_name=%s" % unique_resource_name,
                        "class": "adminlink",
                        "title": "Manage %s" % unique_resource_name,
                        "text": "Manage %s" % unique_resource_name,
                    },
                    {
                        "object_type": "link",
                        "destination": "viewres.py?unique_resource_name=%s" % visible_res_name,
                        "class": "infolink",
                        "title": "View %s" % unique_resource_name,
                        "text": "View %s" % unique_resource_name,
                    },
                ],
            }

            if unique_resource_name in unique_res_names:
                raw_conf_file = os.path.join(configuration.resource_home, unique_resource_name, "config.MiG")
                try:
                    filehandle = open(raw_conf_file, "r")
                    raw_conf = filehandle.readlines()
                    filehandle.close()
                except:
                    raw_conf = [""]

                res_html = display_resource(
                    unique_resource_name, raw_conf, resource_config, owner_list, re_list, configuration
                )
                output_objects.append({"object_type": "html_form", "text": res_html})

                output_objects.append({"object_type": "sectionheader", "text": "Retire resource"})
                output_objects.append(
                    {
                        "object_type": "text",
                        "text": """
Use the link below to permanently remove the resource from the grid after
stopping all units and the front end.
""",
                    }
                )
                js_name = "delres%s" % hexlify(unique_resource_name)
                helper = html_post_helper(js_name, "delres.py", {"unique_resource_name": unique_resource_name})
                output_objects.append({"object_type": "html_form", "text": helper})
                output_objects.append(
                    {
                        "object_type": "link",
                        "destination": "javascript: confirmDialog(%s, '%s');"
                        % (js_name, "Really delete %s? (fails if it is busy)" % unique_resource_name),
                        "class": "removelink",
                        "title": "Delete %s" % unique_resource_name,
                        "text": "Delete %s" % unique_resource_name,
                    }
                )
            owned += 1

    if owned == 0:
        output_objects.append({"object_type": "text", "text": "You are not listed as owner of any resources!"})
    else:
        sorted_links = quick_res.items()
        sorted_links.sort()
        for (res_id, link_obj) in sorted_links:
            quick_links.append(link_obj)

            # add new line

            quick_links.append({"object_type": "text", "text": ""})

        quick_links.append({"object_type": "html_form", "text": '</div><div class="quicklinks">'})
        quick_links.append(
            {
                "object_type": "link",
                "destination": "javascript:toggleHidden('.quicklinks');",
                "class": "additemlink",
                "title": "Toggle view",
                "text": "Show quick links",
            }
        )
        quick_links.append({"object_type": "html_form", "text": "</div>"})

        output_objects = output_objects[:quick_links_index] + quick_links + output_objects[quick_links_index:]

    return (output_objects, returnvalues.OK)
Example #3
0
def validate(configuration, job, vgrid_resource_map, job_cond, errors):
    """Validates the readiness condition of a submitted job in respect to the
    requested specifications of vgrid, resource etc.
    """

    best_job_cond = {}
    best_job_cond['JOB_COND'] = RED
    best_errors = errors
    found_best = False
    other_errors = {}

    # Avoid repeated get_resource_map calls for every single resource
    
    resource_map = get_resource_map(configuration)
    for (vgrid, resources) in vgrid_resource_map.items():

        if best_job_cond['JOB_COND'] == GREEN:
            break

        for resource_id in resources:

            resource = get_resource_configuration(configuration, resource_id, resource_map)

            # vgrid_resource_map may contain e.g. deleted resources
            
            if not resource:
                continue

            # Check resource availability

            job_cond['REGISTERED'] = validate_resource_seen(configuration,
                                                            resource, errors,
                                                            resource_id)
            job_cond['SEEN_WITHIN_X'] = \
            validate_resource_seen_within_x_hours(configuration, resource,
                                                  errors, resource_id)

            # Check mRSL requested specs

            job_cond['ARCHITECTURE'] = validate_architecture(configuration,
                                                             job, resource,
                                                             errors)
            job_cond['CPUCOUNT'] = validate_cpucount(configuration, job,
                                                     resource, errors)
            job_cond['CPUTIME'] = validate_cputime(configuration, job,
                                                   resource, errors)
            job_cond['DISK'] = validate_disk(configuration, job, resource,
                                             errors)
            job_cond['JOBTYPE'] = validate_jobtype(configuration, job,
                                                   resource, errors)
            job_cond['MAXPRICE'] = validate_maxprice(configuration, job,
                                                     resource, errors)
            job_cond['MEMORY'] = validate_memory(configuration, job, resource,
                                                 errors)
            job_cond['NODECOUNT'] = validate_nodecount(configuration, job,
                                                       resource, errors)
            job_cond['PLATFORM'] = validate_platform(configuration, job,
                                                     resource, errors)
            job_cond['RETRIES'] = validate_retries(configuration, job, errors)
            job_cond['RUNTIMEENVIRONMENT'] = validate_runtimeenvironment(
                configuration, job, resource, errors)
            job_cond['SANDBOX'] = validate_sandbox(configuration, job,
                                                   resource, errors)

            job_cond['suggested_vgrid'] = vgrid
            job_cond['suggested_resource'] = anon_resource_id(resource_id,
                                                              False)

            set_pass_level(configuration, job_cond)

            if threshold_color_to_value(job_cond['JOB_COND']) >= \
                   threshold_color_to_value(best_job_cond['JOB_COND']):
                if not found_best or (len(errors) <= len(best_errors)):
                    found_best = True
                    best_job_cond = job_cond.copy()
                    best_errors = errors.copy()

                    if best_job_cond['JOB_COND'] == GREEN:
                        break

            job_cond.clear()
            errors.clear()

    # Run resource independent checks only once

    job_cond['INPUTFILES'] = validate_inputfiles(configuration, job,
                                                 other_errors)
    job_cond['EXECUTABLES'] = validate_executables(configuration, job,
                                                   other_errors)
    job_cond['VERIFYFILES'] = validate_verifyfiles(configuration, job,
                                                   other_errors)
    job_cond['NOTIFY'] = validate_notify(configuration, job, other_errors)

    if not found_best:
        best_job_cond['RESOURCE'] = False
        best_errors['RESOURCE'] = 'No valid/allowed resources available.'
    else:
        best_job_cond.update(job_cond)

    if other_errors:
        best_errors.update(other_errors)
        if best_job_cond['JOB_COND'] == GREEN:
            best_job_cond['JOB_COND'] = YELLOW
    return (best_job_cond, best_errors)
Example #4
0
def get_resource_configuration(configuration, resource_id, resource_map=None):
    """Returns empty dict if resource_id is missing/deleted"""
    if not resource_map:
        resource_map = get_resource_map(configuration)
    return resource_map.get(resource_id, {CONF: {}})[CONF]
Example #5
0
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)
    status = returnvalues.OK
    defaults = signature()[1]
    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Resource management'
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
    )
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    show_sandboxes = (accepted['show_sandboxes'][-1] != 'false')
    operation = accepted['operation'][-1]
    caching = (accepted['caching'][-1].lower() in ('true', 'yes'))

    if not configuration.site_enable_resources:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''Resources are not enabled on this system'''
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    if not operation in allowed_operations:
        output_objects.append({
            'object_type':
            'text',
            'text':
            '''Operation must be one of %s.''' % ', '.join(allowed_operations)
        })
        return (output_objects, returnvalues.OK)

    logger.info("%s %s begin for %s" % (op_name, operation, client_id))
    pending_updates = False
    if operation in show_operations:

        # jquery support for tablesorter and confirmation on delete
        # table initially sorted by col. 1 (admin), then 0 (name)

        # NOTE: We distinguish between caching on page load and forced refresh
        refresh_call = 'ajax_resman(%s)'
        table_spec = {
            'table_id': 'resourcetable',
            'sort_order': '[[1,0],[0,0]]',
            'refresh_call': refresh_call % 'false'
        }
        (add_import, add_init,
         add_ready) = man_base_js(configuration, [table_spec])
        if operation == "show":
            add_ready += '%s;' % refresh_call % 'true'
        title_entry['script']['advanced'] += add_import
        title_entry['script']['init'] += add_init
        title_entry['script']['ready'] += add_ready
        output_objects.append({
            'object_type': 'html_form',
            'text': man_base_html(configuration)
        })

        output_objects.append({
            'object_type': 'header',
            'text': 'Available Resources'
        })

        output_objects.append({
            'object_type': 'sectionheader',
            'text': 'Resources available on this server'
        })
        output_objects.append({
            'object_type':
            'text',
            'text':
            '''
All available resources are listed below with overall hardware specifications.
Any resources that you own will have a administration icon that you can click
to open resource management.
'''
        })

        # Helper forms for requests and removes

        form_method = 'post'
        csrf_limit = get_csrf_limit(configuration)
        target_op = 'sendrequestaction'
        csrf_token = make_csrf_token(configuration, form_method, target_op,
                                     client_id, csrf_limit)
        helper = html_post_helper(
            'reqresowner', '%s.py' % target_op, {
                'unique_resource_name': '__DYNAMIC__',
                'request_type': 'resourceowner',
                'request_text': '',
                csrf_field: csrf_token
            })
        output_objects.append({'object_type': 'html_form', 'text': helper})
        target_op = 'rmresowner'
        csrf_token = make_csrf_token(configuration, form_method, target_op,
                                     client_id, csrf_limit)
        helper = html_post_helper(
            'rmresowner', '%s.py' % target_op, {
                'unique_resource_name': '__DYNAMIC__',
                'cert_id': client_id,
                csrf_field: csrf_token
            })
        output_objects.append({'object_type': 'html_form', 'text': helper})

        output_objects.append({
            'object_type': 'table_pager',
            'entry_name': 'resources',
            'default_entries': default_pager_entries
        })

    resources = []
    if operation in list_operations:
        logger.info("get vgrid and resource map with caching %s" % caching)
        visible_res_confs = user_visible_res_confs(configuration, client_id,
                                                   caching)
        res_map = get_resource_map(configuration, caching)
        anon_map = anon_to_real_res_map(configuration.resource_home)

        if caching:
            modified_resources, _ = check_resources_modified(configuration)
            modified_vgrids, _ = check_vgrids_modified(configuration)
            if modified_resources:
                logger.info("pending resource cache updates: %s" %
                            modified_resources)
                pending_updates = True
            elif modified_vgrids:
                logger.info("pending vgrid cache updates: %s" %
                            modified_vgrids)
                pending_updates = True
            else:
                logger.info("no pending cache updates")

        # Iterate through resources and show management for each one requested

        fields = [
            'PUBLICNAME', 'NODECOUNT', 'CPUCOUNT', 'MEMORY', 'DISK',
            'ARCHITECTURE', 'SANDBOX', 'RUNTIMEENVIRONMENT'
        ]

        # NOTE: only resources that user is allowed to access are listed.
        #       Resource with neither exes nor stores are not shown to anyone
        #       but the owners. Similarly resources are not shown if all
        #       resource units solely participate in VGrids, which the user
        #       can't access.
        for visible_res_name in visible_res_confs.keys():
            unique_resource_name = visible_res_name
            if visible_res_name in anon_map.keys():
                unique_resource_name = anon_map[visible_res_name]

            if not show_sandboxes and sandbox_resource(unique_resource_name):
                continue
            res_obj = {'object_type': 'resource', 'name': visible_res_name}

            if client_id in res_map[unique_resource_name][OWNERS]:

                # Admin of resource when owner

                res_obj['resownerlink'] = {
                    'object_type':
                    'link',
                    'destination':
                    "javascript: confirmDialog(%s, '%s', %s, %s);" %
                    ('rmresowner', 'Really leave %s owners?' %
                     unique_resource_name, 'undefined',
                     "{unique_resource_name: '%s'}" % unique_resource_name),
                    'class':
                    'removelink iconspace',
                    'title':
                    'Leave %s owners' % unique_resource_name,
                    'text':
                    ''
                }
                res_obj['resdetailslink'] = {
                    'object_type': 'link',
                    'destination': 'resadmin.py?unique_resource_name=%s' %
                    unique_resource_name,
                    'class': 'adminlink iconspace',
                    'title': 'Administrate %s' % unique_resource_name,
                    'text': ''
                }
            else:

                # link to become owner

                res_obj['resownerlink'] = {
                    'object_type':
                    'link',
                    'destination':
                    "javascript: confirmDialog(%s, '%s', '%s', %s);" %
                    ('reqresowner',
                     "Request ownership of " + visible_res_name + ":<br/>" +
                     "\nPlease write a message to the owners (field below).",
                     'request_text',
                     "{unique_resource_name: '%s'}" % visible_res_name),
                    'class':
                    'addlink iconspace',
                    'title':
                    'Request ownership of %s' % visible_res_name,
                    'text':
                    ''
                }

                res_obj['resdetailslink'] = {
                    'object_type': 'link',
                    'destination':
                    'viewres.py?unique_resource_name=%s' % visible_res_name,
                    'class': 'infolink iconspace',
                    'title': 'View detailed %s specs' % visible_res_name,
                    'text': ''
                }

            # fields for everyone: public status
            for name in fields:
                res_obj[name] = res_map[unique_resource_name][CONF].get(
                    name, '')
            # Use runtimeenvironment names instead of actual definitions
            res_obj['RUNTIMEENVIRONMENT'] = [
                i[0] for i in res_obj['RUNTIMEENVIRONMENT']
            ]
            res_obj['RUNTIMEENVIRONMENT'].sort()
            resources.append(res_obj)

    if operation == "show":
        # insert dummy placeholder to build table
        res_obj = {'object_type': 'resource', 'name': ''}
        resources.append(res_obj)

    output_objects.append({
        'object_type': 'resource_list',
        'pending_updates': pending_updates,
        'resources': resources
    })

    if operation in show_operations:
        if configuration.site_enable_sandboxes:
            if show_sandboxes:
                output_objects.append({
                    'object_type': 'link',
                    'destination': '?show_sandboxes=false',
                    'class': 'removeitemlink iconspace',
                    'title': 'Hide sandbox resources',
                    'text': 'Exclude sandbox resources',
                })

            else:
                output_objects.append({
                    'object_type': 'link',
                    'destination': '?show_sandboxes=true',
                    'class': 'additemlink iconspace',
                    'title': 'Show sandbox resources',
                    'text': 'Include sandbox resources',
                })

        output_objects.append({
            'object_type': 'sectionheader',
            'text': 'Resource Status'
        })
        output_objects.append({
            'object_type':
            'text',
            'text':
            '''
Live resource status is available in the resource monitor page with all
%s/resources you can access
''' % configuration.site_vgrid_label
        })
        output_objects.append({
            'object_type': 'link',
            'destination': 'showvgridmonitor.py?vgrid_name=ALL',
            'class': 'monitorlink iconspace',
            'title': 'Show monitor with all resources you can access',
            'text': 'Global resource monitor',
        })

        output_objects.append({
            'object_type': 'sectionheader',
            'text': 'Additional Resources'
        })
        output_objects.append({
            'object_type':
            'text',
            'text':
            'You can sign up spare or dedicated resources to the grid below.'
        })
        output_objects.append({
            'object_type':
            'link',
            'destination':
            'resedit.py',
            'class':
            'addlink iconspace',
            'title':
            'Show sandbox resources',
            'text':
            'Create a new %s resource' % configuration.short_title,
        })
        output_objects.append({'object_type': 'sectionheader', 'text': ''})

        if configuration.site_enable_sandboxes:
            output_objects.append({
                'object_type':
                'link',
                'destination':
                'ssslogin.py',
                'class':
                'adminlink iconspace',
                'title':
                'Administrate and monitor your sandbox resources',
                'text':
                'Administrate %s sandbox resources' % configuration.short_title
            })
            output_objects.append({'object_type': 'sectionheader', 'text': ''})
            output_objects.append({
                'object_type':
                'link',
                'destination':
                'oneclick.py',
                'class':
                'sandboxlink iconspace',
                'title':
                'Run a One-click resource in your browser',
                'text':
                'Use this computer as One-click %s resource' %
                configuration.short_title
            })

    logger.info("%s %s end for %s" % (op_name, operation, client_id))
    return (output_objects, status)
Example #6
0
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)
    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:
        return (accepted, returnvalues.CLIENT_ERROR)

    show_sandboxes = (accepted['show_sandboxes'][-1] != 'false')

    visible_exes = user_visible_res_exes(configuration, client_id)
    res_map = get_resource_map(configuration)
    anon_map = anon_to_real_res_map(configuration.resource_home)

    # Iterate through resources and show management for each one requested

    res_list = {'object_type': 'resource_list', 'resources': []}
    fields = ['PUBLICNAME', 'NODECOUNT', 'CPUCOUNT', 'MEMORY', 'DISK', 'ARCHITECTURE',
              'SANDBOX', 'RUNTIMEENVIRONMENT']
    # Leave the sorting to jquery tablesorter
    for visible_res_name in visible_exes.keys():
        unique_resource_name = visible_res_name
        if visible_res_name in anon_map.keys():
            unique_resource_name = anon_map[visible_res_name]

        if not show_sandboxes and sandbox_resource(unique_resource_name):
            continue
        res_obj = {'object_type': 'resource', 'name': visible_res_name}

        if client_id in res_map[unique_resource_name][OWNERS]:

            # Admin of resource when owner

            js_name = 'rmresowner%s' % hexlify(unique_resource_name)
            helper = html_post_helper(js_name, 'rmresowner.py',
                                      {'unique_resource_name':
                                       unique_resource_name,
                                       'cert_id': client_id})
            output_objects.append({'object_type': 'html_form', 'text': helper})
            res_obj['resownerlink'] = \
                                    {'object_type': 'link',
                                     'destination':
                                     "javascript: confirmDialog(%s, '%s');"\
                                     % (js_name, 'Really leave %s owners?' % \
                                        unique_resource_name),
                                     'class': 'removelink',
                                     'title': 'Leave %s owners' % unique_resource_name, 
                                     'text': ''}
            res_obj['resdetailslink'] = \
                                    {'object_type': 'link',
                                     'destination':
                                     'resadmin.py?unique_resource_name=%s'\
                                     % unique_resource_name,
                                     'class': 'adminlink',
                                     'title': 'Administrate %s' % unique_resource_name, 
                                     'text': ''}
        else:

            # link to become owner

            js_name = 'reqresowner%s' % hexlify(unique_resource_name)
            helper = html_post_helper(js_name, 'sendrequestaction.py',
                                      {'unique_resource_name':
                                       visible_res_name,
                                       'request_type': 'resourceowner',
                                       'request_text': ''})
            output_objects.append({'object_type': 'html_form', 'text': helper})
            res_obj['resownerlink'] = \
                                    {'object_type': 'link',
                                     'destination':
                                     "javascript: confirmDialog(%s, '%s', '%s');"\
                                     % (js_name, "Request ownership of " + \
                                        visible_res_name + ":<br/>" + \
                                        "\nPlease write a message to the owners (field below).",
                                        'request_text'),
                                     'class': 'addlink',
                                     'title': 'Request ownership of %s' % visible_res_name,
                                     'text': ''}
            
            res_obj['resdetailslink'] = \
                                    {'object_type': 'link',
                                     'destination':
                                     'viewres.py?unique_resource_name=%s'\
                                     % visible_res_name,
                                     'class': 'infolink',
                                     'title': 'View detailed %s specs' % \
                                     visible_res_name, 
                                     'text': ''}
            
        # fields for everyone: public status
        for name in fields:
            res_obj[name] = res_map[unique_resource_name][CONF].get(name, '')
        # Use runtimeenvironment names instead of actual definitions
        res_obj['RUNTIMEENVIRONMENT'] = [i[0] for i in res_obj['RUNTIMEENVIRONMENT']]
        res_list['resources'].append(res_obj)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Resource management'

    # jquery support for tablesorter and confirmation on "leave":

    title_entry['style'] = themed_styles(configuration)
    title_entry['javascript'] = '''
<script type="text/javascript" src="/images/js/jquery.js"></script>
<script type="text/javascript" src="/images/js/jquery.tablesorter.js"></script>
<script type="text/javascript" src="/images/js/jquery.tablesorter.pager.js"></script>
<script type="text/javascript" src="/images/js/jquery.tablesorter.widgets.js"></script>
<script type="text/javascript" src="/images/js/jquery-ui.js"></script>
<script type="text/javascript" src="/images/js/jquery.confirm.js"></script>

<script type="text/javascript" >

$(document).ready(function() {

          // init confirmation dialog
          $( "#confirm_dialog" ).dialog(
              // see http://jqueryui.com/docs/dialog/ for options
              { autoOpen: false,
                modal: true, closeOnEscape: true,
                width: 500,
                buttons: {
                   "Cancel": function() { $( "#" + name ).dialog("close"); }
                }
              });

          // table initially sorted by col. 1 (admin), then 0 (name)
          var sortOrder = [[1,0],[0,0]];

          // use image path for sorting if there is any inside
          var imgTitle = function(contents) {
              var key = $(contents).find("a").attr("class");
              if (key == null) {
                  key = $(contents).html();
              }
              return key;
          }
          
          $("#resourcetable").tablesorter({widgets: ["zebra", "saveSort"],
                                        sortList:sortOrder,
                                        textExtraction: imgTitle
                                        })
                             .tablesorterPager({ container: $("#pager"),
                                        size: %s
                                        });
     }
);
</script>
''' % default_pager_entries

    output_objects.append({'object_type': 'html_form',
                           'text':'''
 <div id="confirm_dialog" title="Confirm" style="background:#fff;">
  <div id="confirm_text"><!-- filled by js --></div>
   <textarea cols="40" rows="4" id="confirm_input" style="display:none;"></textarea>
 </div>
'''                       })

    output_objects.append({'object_type': 'header', 'text': 'Available Resources'
                          })

    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Resources available on this server'})
    output_objects.append({'object_type': 'text', 'text'
                          : '''
All available resources are listed below with overall hardware specifications. Any resources that you own will have a administration icon that you can click to open resource management.
'''
                       })

    output_objects.append({'object_type': 'table_pager', 'entry_name': 'resources',
                           'default_entries': default_pager_entries})
    output_objects.append(res_list)

    if configuration.site_enable_sandboxes:
        if show_sandboxes:
            output_objects.append({'object_type': 'link',
                                   'destination': '?show_sandboxes=false',
                                   'class': 'removeitemlink',
                                   'title': 'Hide sandbox resources', 
                                   'text': 'Exclude sandbox resources',
                                   })

        else:
            output_objects.append({'object_type': 'link',
                                   'destination': '?show_sandboxes=true',
                                   'class': 'additemlink',
                                   'title': 'Show sandbox resources', 
                                   'text': 'Include sandbox resources',
                                   })

    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Resource Status'})
    output_objects.append({'object_type': 'text',
                           'text': '''
Live resource status is available in the resource monitor page with all
%s/resources you can access
''' % configuration.site_vgrid_label})
    output_objects.append({'object_type': 'link',
                           'destination': 'showvgridmonitor.py?vgrid_name=ALL',
                           'class': 'monitorlink',
                           'title': 'Show monitor with all resources you can access', 
                           'text': 'Global resource monitor',
                           })

    output_objects.append({'object_type': 'sectionheader', 'text': 'Additional Resources'
                          })
    output_objects.append({'object_type': 'text',
                           'text': 'You can sign up spare or dedicated resources to the grid below.'
                           })
    output_objects.append({'object_type': 'link',
                           'destination' : 'resedit.py',
                           'class': 'addlink',
                           'title': 'Show sandbox resources',                            
                           'text': 'Create a new %s resource' % \
                           configuration.short_title, 
                           })
    output_objects.append({'object_type': 'sectionheader', 'text': ''})

    if configuration.site_enable_sandboxes:
        output_objects.append({'object_type': 'link',
                               'destination': 'ssslogin.py',
                               'class': 'adminlink',
                               'title': 'Administrate and monitor your sandbox resources',
                               'text': 'Administrate %s sandbox resources' % \
                               configuration.short_title,
                               })
        output_objects.append({'object_type': 'sectionheader', 'text': ''})
        output_objects.append({'object_type': 'link',
                               'destination': 'oneclick.py',
                               'class': 'sandboxlink',
                               'title': 'Run a One-click resource in your browser', 
                               'text': 'Use this computer as One-click %s resource' % \
                               configuration.short_title,
                               })

    return (output_objects, status)
Example #7
0
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)
    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:
        return (accepted, returnvalues.CLIENT_ERROR)

    if not correct_handler('POST'):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : 'Only accepting POST requests to prevent unintended updates'})
        return (output_objects, returnvalues.CLIENT_ERROR)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s send request' % \
                            configuration.short_title
    output_objects.append({'object_type': 'header', 'text'
                          : '%s send request' % \
                            configuration.short_title})

    target_id = client_id
    vgrid_name = accepted['vgrid_name'][-1].strip()
    visible_user_name = accepted['cert_id'][-1].strip()
    visible_res_name = accepted['unique_resource_name'][-1].strip()
    request_type = accepted['request_type'][-1].strip().lower()
    request_text = accepted['request_text'][-1].strip()
    protocols = [proto.strip() for proto in accepted['protocol']]
    use_any = False
    if any_protocol in protocols:
        use_any = True
        protocols = configuration.notify_protocols
    protocols = [proto.lower() for proto in protocols]

    valid_request_types = ['resourceowner', 'resourceaccept', 'vgridowner',
                           'vgridmember','vgridresource', 'vgridaccept',
                           'plain']
    if not request_type in valid_request_types:
        output_objects.append({
            'object_type': 'error_text', 'text'
            : '%s is not a valid request_type (valid types: %s)!'
            % (request_type.lower(),
               valid_request_types)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if not protocols:
        output_objects.append({
            'object_type': 'error_text', 'text':
            'No protocol specified!'})
        return (output_objects, returnvalues.CLIENT_ERROR)

    user_map = get_user_map(configuration)
    reply_to = user_map[client_id][USERID]

    if request_type == "plain":
        if not visible_user_name:
            output_objects.append({
                'object_type': 'error_text', 'text':
                'No user ID specified!'})
            return (output_objects, returnvalues.CLIENT_ERROR)

        user_id = visible_user_name
        anon_map = anon_to_real_user_map(configuration.user_home)
        if anon_map.has_key(visible_user_name):
            user_id = anon_map[visible_user_name]
        if not user_map.has_key(user_id):
            output_objects.append({'object_type': 'error_text',
                                   'text': 'No such user: %s' % \
                                   visible_user_name
                                   })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_name = user_id
        user_dict = user_map[user_id]
        allow_vgrids = user_allowed_vgrids(configuration, client_id)
        vgrids_allow_email = user_dict[CONF].get('VGRIDS_ALLOW_EMAIL', [])
        vgrids_allow_im = user_dict[CONF].get('VGRIDS_ALLOW_IM', [])
        if any_vgrid in vgrids_allow_email:
            email_vgrids = allow_vgrids
        else:
            email_vgrids = set(vgrids_allow_email).intersection(allow_vgrids)
        if any_vgrid in vgrids_allow_im:
            im_vgrids = allow_vgrids
        else:
            im_vgrids = set(vgrids_allow_im).intersection(allow_vgrids)
        if use_any:
            # Do not try disabled protocols if ANY was requested
            if not email_vgrids:
                protocols = [proto for proto in protocols \
                             if proto not in email_keyword_list]
            if not im_vgrids:
                protocols = [proto for proto in protocols \
                             if proto in email_keyword_list]
        if not email_vgrids and [proto for proto in protocols \
                                 if proto in email_keyword_list]:
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'You are not allowed to send emails to %s!' % \
                visible_user_name
                })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not im_vgrids and [proto for proto in protocols \
                              if proto not in email_keyword_list]:
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'You are not allowed to send instant messages to %s!' % \
                visible_user_name
                })
            return (output_objects, returnvalues.CLIENT_ERROR)
        for proto in protocols:
            if not user_dict[CONF].get(proto.upper(), False):
                if use_any:
                    # Remove missing protocols if ANY protocol was requested
                    protocols = [i for i in protocols if i != proto]
                else:
                    output_objects.append({
                        'object_type': 'error_text', 'text'
                        : 'User %s does not accept %s messages!' % \
                        (visible_user_name, proto)
                        })
                    return (output_objects, returnvalues.CLIENT_ERROR)
        if not protocols:
            output_objects.append({
                'object_type': 'error_text', 'text':
                'User %s does not accept requested protocol(s) messages!' % \
                visible_user_name})
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_list = [user_id]
    elif request_type == "vgridaccept":
        # Always allow accept messages but only between vgrid members/owners
        user_id = visible_user_name
        if not vgrid_name:
            output_objects.append({
                'object_type': 'error_text', 'text': 'No vgrid_name specified!'})
            return (output_objects, returnvalues.CLIENT_ERROR)
        if vgrid_name.upper() == default_vgrid.upper():
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'No requests for %s are not allowed!' % \
                default_vgrid
                })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not vgrid_is_owner(vgrid_name, client_id, configuration):
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'You are not an owner of %s or a parent %s!' % \
                (vgrid_name, configuration.site_vgrid_label)})
            return (output_objects, returnvalues.CLIENT_ERROR)
        allow_vgrids = user_allowed_vgrids(configuration, client_id)
        if not vgrid_name in allow_vgrids:
            output_objects.append({
                'object_type': 'error_text', 'text':
                'Invalid %s message! (%s sv %s)' % (request_type, user_id,
                                                    allow_vgrids)})
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_id = '%s %s owners' % (vgrid_name, configuration.site_vgrid_label)
        target_name = vgrid_name
        target_list = [user_id]
    elif request_type == "resourceaccept":
        # Always allow accept messages between actual resource owners
        user_id = visible_user_name
        if not visible_res_name:
            output_objects.append({
                'object_type': 'error_text', 'text':
                'No resource ID specified!'})
            return (output_objects, returnvalues.CLIENT_ERROR)
        unique_resource_name = visible_res_name
        target_name = unique_resource_name
        res_map = get_resource_map(configuration)
        if not res_map.has_key(unique_resource_name):
            output_objects.append({'object_type': 'error_text',
                                   'text': 'No such resource: %s' % \
                                   unique_resource_name
                                   })
            return (output_objects, returnvalues.CLIENT_ERROR)
        owners_list = res_map[unique_resource_name][OWNERS]
        if not client_id in owners_list or not user_id in owners_list:
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'Invalid resource owner accept message!'})
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_id = '%s resource owners' % unique_resource_name
        target_name = unique_resource_name
        target_list = [user_id]
    elif request_type == "resourceowner":
        if not visible_res_name:
            output_objects.append({
                'object_type': 'error_text', 'text':
                'No resource ID specified!'})
            return (output_objects, returnvalues.CLIENT_ERROR)
        
        unique_resource_name = visible_res_name
        anon_map = anon_to_real_res_map(configuration.resource_home)
        if anon_map.has_key(visible_res_name):
            unique_resource_name = anon_map[visible_res_name]
        target_name = unique_resource_name
        res_map = get_resource_map(configuration)
        if not res_map.has_key(unique_resource_name):
            output_objects.append({'object_type': 'error_text',
                                   'text': 'No such resource: %s' % \
                                   visible_res_name
                                   })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_list = res_map[unique_resource_name][OWNERS]
        if client_id in target_list:
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'You are already an owner of %s!' % unique_resource_name
                })
            return (output_objects, returnvalues.CLIENT_ERROR)
    elif request_type in ["vgridmember", "vgridowner", "vgridresource"]:
        unique_resource_name = visible_res_name
        if not vgrid_name:
            output_objects.append({
                'object_type': 'error_text', 'text': 'No vgrid_name specified!'})
            return (output_objects, returnvalues.CLIENT_ERROR)

        # default vgrid is read-only
        
        if vgrid_name.upper() == default_vgrid.upper():
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'No requests for %s are not allowed!' % \
                default_vgrid
                })
            return (output_objects, returnvalues.CLIENT_ERROR)

        # stop owner or member request if already an owner

        if request_type != 'vgridresource':
            if vgrid_is_owner(vgrid_name, client_id, configuration):
                output_objects.append({
                    'object_type': 'error_text', 'text'
                    : 'You are already an owner of %s or a parent %s!' % \
                    (vgrid_name, configuration.site_vgrid_label)})
                return (output_objects, returnvalues.CLIENT_ERROR)

        # only ownership requests are allowed for existing members

        if request_type == 'vgridmember':
            if vgrid_is_member(vgrid_name, client_id, configuration):
                output_objects.append({
                    'object_type': 'error_text', 'text'
                    : 'You are already a member of %s or a parent %s.' % \
                    (vgrid_name, configuration.site_vgrid_label)})
                return (output_objects, returnvalues.CLIENT_ERROR)

        # set target to resource and prevent repeated resource access requests

        if request_type == 'vgridresource':
            target_id = unique_resource_name
            if vgrid_is_resource(vgrid_name, unique_resource_name,
                                 configuration):
                output_objects.append({
                    'object_type': 'error_text', 'text'
                    : 'You already have access to %s or a parent %s.' % \
                    (vgrid_name, configuration.site_vgrid_label)})
                return (output_objects, returnvalues.CLIENT_ERROR)

        # Find all VGrid owners

        target_name = vgrid_name
        (status, target_list) = vgrid_list(vgrid_name, 'owners', configuration)
        if not status:
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'Could not load list of current owners for %s %s!'
                % (vgrid_name, configuration.site_vgrid_label)})
            return (output_objects, returnvalues.CLIENT_ERROR)

    else:
        output_objects.append({
            'object_type': 'error_text', 'text': 'Invalid request type: %s' % \
            request_type})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Now send request to all targets in turn
    # TODO: inform requestor if no owners have mail/IM set in their settings
    
    for target in target_list:
        # USER_CERT entry is destination

        notify = []
        for proto in protocols:
            notify.append('%s: SETTINGS' % proto)
        job_dict = {'NOTIFY': notify, 'JOB_ID': 'NOJOBID', 'USER_CERT': target}

        notifier = notify_user_thread(
            job_dict,
            [target_id, target_name, request_type, request_text, reply_to],
            'SENDREQUEST',
            logger,
            '',
            configuration,
            )

        # Try finishing delivery but do not block forever on one message
        notifier.join(30)
    output_objects.append({'object_type': 'text', 'text':
                           'Sent %s message to %d people' % \
                           (request_type, len(target_list))})
    output_objects.append({'object_type': 'text', 'text':
                           """Please make sure you have notifications
configured on your Setings page if you expect a reply to this message"""})
    
    return (output_objects, returnvalues.OK)
Example #8
0
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)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Resource details'
    output_objects.append({'object_type': 'header', 'text'
                          : 'Show resource details'})

    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:
        return (accepted, returnvalues.CLIENT_ERROR)
    resource_list = accepted['unique_resource_name']
    status = returnvalues.OK
    visible_res = user_visible_res_confs(configuration, client_id)
    vgrid_access = user_vgrid_access(configuration, client_id)
    res_map = get_resource_map(configuration)
    anon_map = anon_to_real_res_map(configuration.resource_home)

    for visible_res_name in resource_list:
        unique_resource_name = visible_res_name
        if visible_res_name in anon_map.keys():
            unique_resource_name = anon_map[visible_res_name]
        if not visible_res_name in visible_res.keys():
            logger.warning('User %s not allowed to view %s (%s)' % \
                           (client_id, visible_res_name, visible_res.keys()))
            output_objects.append({'object_type': 'error_text',
                                   'text': 'invalid resource %s' % \
                                   visible_res_name})
            continue
        res_dict = visible_res[visible_res_name]
        res_item = build_resitem_object_from_res_dict(configuration,
                                                      visible_res_name,
                                                      res_dict,
                                                      vgrid_access)
        output_objects.append(res_item)

    
        if client_id in res_map[unique_resource_name][OWNERS]:
            output_objects.append({'object_type': 'sectionheader',
                                   'text': 'Administrate'})
            output_objects.append({'object_type': 'link',
                                     'destination':
                                     'resadmin.py?unique_resource_name=%s'\
                                     % unique_resource_name,
                                     'class': 'adminlink iconspace',
                                     'title': 'Administrate %s' % unique_resource_name, 
                                     'text': 'Administrate %s' % unique_resource_name,
                                   })

        
    return (output_objects, status)
Example #9
0
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)
    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:
        return (accepted, returnvalues.CLIENT_ERROR)

    unique_res_names = accepted['unique_resource_name']

    if not configuration.site_enable_resources:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''Resources are not enabled on this system'''
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # prepare for confirm dialog, tablesort and toggling the views (css/js)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = "Resource Administration"

    # jquery support for tablesorter and confirmation on request and leave
    # requests table initially sorted by 4, 3 (date first and with alphabetical
    # client ID)

    table_specs = [{
        'table_id': 'accessrequeststable',
        'pager_id': 'accessrequests_pager',
        'sort_order': '[[4,0],[3,0]]'
    }]
    (add_import, add_init, add_ready) = man_base_js(configuration, table_specs,
                                                    {'width': 600})
    add_init += '''
        var toggleHidden = function(classname) {
            // classname supposed to have a leading dot 
            $(classname).toggleClass("hidden");
        };
        /* helper for dynamic form input fields */
        function onOwnerInputChange() {
            makeSpareFields("#dynownerspares", "cert_id");
        }
    '''
    add_ready += '''
    /* init add owners form with dynamic input fields */
    onOwnerInputChange();
    $("#dynownerspares").on("blur", "input[name=cert_id]", 
        function(event) {
            //console.debug("in add owner blur handler");
            onOwnerInputChange();
        }
    );
    '''
    title_entry['script']['advanced'] += add_import
    title_entry['script']['init'] += add_init
    title_entry['script']['ready'] += add_ready
    output_objects.append({
        'object_type': 'html_form',
        'text': man_base_html(configuration)
    })

    form_method = 'post'
    csrf_limit = get_csrf_limit(configuration)
    fill_helpers = {
        'short_title': configuration.short_title,
        'vgrid_label': configuration.site_vgrid_label,
        'form_method': form_method,
        'csrf_field': csrf_field,
        'csrf_limit': csrf_limit
    }

    (re_stat, re_list) = list_runtime_environments(configuration)
    if not re_stat:
        logger.warning('Failed to load list of runtime environments')
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Error getting list of runtime environments'
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    output_objects.append({'object_type': 'header', 'text': 'Manage Resource'})

    output_objects.append({
        'object_type':
        'sectionheader',
        'text':
        '%(short_title)s Resources Owned' % fill_helpers
    })
    quick_links = [{
        'object_type':
        'text',
        'text':
        'Quick links to all your resources and individual management'
    }]
    quick_links.append({
        'object_type': 'html_form',
        'text': '<div class="hidden quicklinks">'
    })
    quick_links.append({
        'object_type': 'link',
        'destination': "javascript:toggleHidden('.quicklinks');",
        'class': 'removeitemlink iconspace',
        'title': 'Toggle view',
        'text': 'Hide quick links'
    })
    quick_links.append({'object_type': 'text', 'text': ''})

    quick_res = {}
    quick_links_index = len(output_objects)
    output_objects.append({'object_type': 'sectionheader', 'text': ''})

    owned = 0
    res_map = get_resource_map(configuration)
    for unique_resource_name in res_map.keys():
        if sandbox_resource(unique_resource_name):
            continue
        owner_list = res_map[unique_resource_name][OWNERS]
        resource_config = res_map[unique_resource_name][CONF]
        visible_res_name = res_map[unique_resource_name][RESID]
        if client_id in owner_list:
            quick_res[unique_resource_name] = {
                'object_type':
                'multilinkline',
                'links': [{
                    'object_type': 'link',
                    'destination':
                    '?unique_resource_name=%s' % unique_resource_name,
                    'class': 'adminlink iconspace',
                    'title': 'Manage %s' % unique_resource_name,
                    'text': 'Manage %s' % unique_resource_name,
                }, {
                    'object_type':
                    'link',
                    'destination':
                    'viewres.py?unique_resource_name=%s' % visible_res_name,
                    'class':
                    'infolink iconspace',
                    'title':
                    'View %s' % unique_resource_name,
                    'text':
                    'View %s' % unique_resource_name,
                }]
            }

            if unique_resource_name in unique_res_names:
                raw_conf_file = os.path.join(configuration.resource_home,
                                             unique_resource_name,
                                             'config.MiG')
                try:
                    filehandle = open(raw_conf_file, 'r')
                    raw_conf = filehandle.readlines()
                    filehandle.close()
                except:
                    raw_conf = ['']

                res_html = display_resource(client_id, unique_resource_name,
                                            raw_conf, resource_config,
                                            owner_list, re_list, configuration,
                                            fill_helpers)
                output_objects.append({
                    'object_type': 'html_form',
                    'text': res_html
                })

                # Pending requests

                target_op = "addresowner"
                csrf_token = make_csrf_token(configuration, form_method,
                                             target_op, client_id, csrf_limit)
                helper = html_post_helper(
                    target_op, "%s.py" % target_op, {
                        'unique_resource_name': unique_resource_name,
                        'cert_id': '__DYNAMIC__',
                        'request_name': '__DYNAMIC__',
                        csrf_field: csrf_token
                    })
                output_objects.append({
                    'object_type': 'html_form',
                    'text': helper
                })
                target_op = "rejectresreq"
                csrf_token = make_csrf_token(configuration, form_method,
                                             target_op, client_id, csrf_limit)
                helper = html_post_helper(
                    target_op, "%s.py" % target_op, {
                        'unique_resource_name': unique_resource_name,
                        'request_name': '__DYNAMIC__',
                        csrf_field: csrf_token
                    })
                output_objects.append({
                    'object_type': 'html_form',
                    'text': helper
                })

                request_dir = os.path.join(configuration.resource_home,
                                           unique_resource_name)
                request_list = []
                for req_name in list_access_requests(configuration,
                                                     request_dir):
                    req = load_access_request(configuration, request_dir,
                                              req_name)
                    if not req:
                        continue
                    if req.get('request_type', None) != "resourceowner":
                        logger.error(
                            "unexpected request_type %(request_type)s" % req)
                        continue
                    request_item = build_accessrequestitem_object(
                        configuration, req)
                    # Convert filename with exotic chars into url-friendly pure hex version
                    shared_args = {
                        "unique_resource_name": unique_resource_name,
                        "request_name": hexlify(req["request_name"])
                    }
                    accept_args, reject_args = {}, {}
                    accept_args.update(shared_args)
                    reject_args.update(shared_args)
                    if req['request_type'] == "resourceowner":
                        accept_args["cert_id"] = req["entity"]
                    request_item['acceptrequestlink'] = {
                        'object_type':
                        'link',
                        'destination':
                        "javascript: confirmDialog(%s, '%s', %s, %s);" %
                        ("addresowner",
                         "Accept %(target)s %(request_type)s request from %(entity)s"
                         % req, 'undefined', "{%s}" % ', '.join([
                             "'%s': '%s'" % pair
                             for pair in accept_args.items()
                         ])),
                        'class':
                        'addlink iconspace',
                        'title':
                        'Accept %(target)s %(request_type)s request from %(entity)s'
                        % req,
                        'text':
                        ''
                    }
                    request_item['rejectrequestlink'] = {
                        'object_type':
                        'link',
                        'destination':
                        "javascript: confirmDialog(%s, '%s', %s, %s);" %
                        ("rejectresreq",
                         "Reject %(target)s %(request_type)s request from %(entity)s"
                         % req, 'undefined', "%s" % reject_args),
                        'class':
                        'removelink iconspace',
                        'title':
                        'Reject %(target)s %(request_type)s request from %(entity)s'
                        % req,
                        'text':
                        ''
                    }

                    request_list.append(request_item)

                output_objects.append({
                    'object_type': 'sectionheader',
                    'text': "Pending Requests"
                })
                output_objects.append({
                    'object_type': 'table_pager',
                    'id_prefix': 'accessrequests_',
                    'entry_name': 'access requests',
                    'default_entries': default_pager_entries
                })
                output_objects.append({
                    'object_type': 'accessrequests',
                    'accessrequests': request_list
                })

                output_objects.append({
                    'object_type': 'sectionheader',
                    'text': 'Retire resource'
                })
                output_objects.append({
                    'object_type':
                    'text',
                    'text':
                    '''
Use the link below to permanently remove the resource from the grid after
stopping all units and the front end.
'''
                })
                target_op = "delres"
                csrf_token = make_csrf_token(configuration, form_method,
                                             target_op, client_id, csrf_limit)
                js_name = 'delres%s' % hexlify(unique_resource_name)
                helper = html_post_helper(
                    js_name, '%s.py' % target_op, {
                        'unique_resource_name': unique_resource_name,
                        csrf_field: csrf_token
                    })
                output_objects.append({
                    'object_type': 'html_form',
                    'text': helper
                })
                output_objects.append({
                    'object_type':
                    'link',
                    'destination':
                    "javascript: confirmDialog(%s, '%s');" %
                    (js_name, 'Really delete %s? (fails if it is busy)' %
                     unique_resource_name),
                    'class':
                    'removelink iconspace',
                    'title':
                    'Delete %s' % unique_resource_name,
                    'text':
                    'Delete %s' % unique_resource_name
                })
            owned += 1

    if owned == 0:
        output_objects.append({
            'object_type':
            'text',
            'text':
            'You are not listed as owner of any resources!'
        })
    else:
        sorted_links = quick_res.items()
        sorted_links.sort()
        for (res_id, link_obj) in sorted_links:
            quick_links.append(link_obj)

            # add new line

            quick_links.append({'object_type': 'text', 'text': ''})

        quick_links.append({
            'object_type': 'html_form',
            'text': '</div><div class="quicklinks">'
        })
        quick_links.append({
            'object_type': 'link',
            'destination': "javascript:toggleHidden('.quicklinks');",
            'class': 'additemlink iconspace',
            'title': 'Toggle view',
            'text': 'Show quick links'
        })
        quick_links.append({'object_type': 'html_form', 'text': '</div>'})

        output_objects = output_objects[:quick_links_index]\
            + quick_links + output_objects[quick_links_index:]

    return (output_objects, returnvalues.OK)
Example #10
0
def get_resource_configuration(configuration, resource_id, resource_map=None):
    """Returns empty dict if resource_id is missing/deleted"""
    if not resource_map:
        resource_map = get_resource_map(configuration)
    return resource_map.get(resource_id, {CONF: {}})[CONF]
Example #11
0
def validate(configuration, job, vgrid_resource_map, job_cond, errors):
    """Validates the readiness condition of a submitted job in respect to the
    requested specifications of vgrid, resource etc.
    """

    best_job_cond = {}
    best_job_cond['JOB_COND'] = RED
    best_errors = errors
    found_best = False
    other_errors = {}

    # Avoid repeated get_resource_map calls for every single resource

    resource_map = get_resource_map(configuration)
    for (vgrid, resources) in vgrid_resource_map.items():

        if best_job_cond['JOB_COND'] == GREEN:
            break

        for resource_id in resources:

            resource = get_resource_configuration(configuration, resource_id,
                                                  resource_map)

            # vgrid_resource_map may contain e.g. deleted resources

            if not resource:
                continue

            # Check resource availability

            job_cond['REGISTERED'] = validate_resource_seen(
                configuration, resource, errors, resource_id)
            job_cond['SEEN_WITHIN_X'] = \
                validate_resource_seen_within_x_hours(configuration, resource,
                                                      errors, resource_id)

            # Check mRSL requested specs

            job_cond['ARCHITECTURE'] = validate_architecture(
                configuration, job, resource, errors)
            job_cond['CPUCOUNT'] = validate_cpucount(configuration, job,
                                                     resource, errors)
            job_cond['CPUTIME'] = validate_cputime(configuration, job,
                                                   resource, errors)
            job_cond['DISK'] = validate_disk(configuration, job, resource,
                                             errors)
            job_cond['JOBTYPE'] = validate_jobtype(configuration, job,
                                                   resource, errors)
            job_cond['MAXPRICE'] = validate_maxprice(configuration, job,
                                                     resource, errors)
            job_cond['MEMORY'] = validate_memory(configuration, job, resource,
                                                 errors)
            job_cond['NODECOUNT'] = validate_nodecount(configuration, job,
                                                       resource, errors)
            job_cond['PLATFORM'] = validate_platform(configuration, job,
                                                     resource, errors)
            job_cond['RETRIES'] = validate_retries(configuration, job, errors)
            job_cond['RUNTIMEENVIRONMENT'] = validate_runtimeenvironment(
                configuration, job, resource, errors)
            job_cond['SANDBOX'] = validate_sandbox(configuration, job,
                                                   resource, errors)

            job_cond['suggested_vgrid'] = vgrid
            job_cond['suggested_resource'] = anon_resource_id(
                resource_id, False)

            set_pass_level(configuration, job_cond)

            if threshold_color_to_value(job_cond['JOB_COND']) >= \
                    threshold_color_to_value(best_job_cond['JOB_COND']):
                if not found_best or (len(errors) <= len(best_errors)):
                    found_best = True
                    best_job_cond = job_cond.copy()
                    best_errors = errors.copy()

                    if best_job_cond['JOB_COND'] == GREEN:
                        break

            job_cond.clear()
            errors.clear()

    # Run resource independent checks only once

    job_cond['INPUTFILES'] = validate_inputfiles(configuration, job,
                                                 other_errors)
    job_cond['EXECUTABLES'] = validate_executables(configuration, job,
                                                   other_errors)
    job_cond['VERIFYFILES'] = validate_verifyfiles(configuration, job,
                                                   other_errors)
    job_cond['NOTIFY'] = validate_notify(configuration, job, other_errors)

    if not found_best:
        best_job_cond['RESOURCE'] = False
        best_errors['RESOURCE'] = 'No valid/allowed resources available.'
    else:
        best_job_cond.update(job_cond)

    if other_errors:
        best_errors.update(other_errors)
        if best_job_cond['JOB_COND'] == GREEN:
            best_job_cond['JOB_COND'] = YELLOW
    return (best_job_cond, best_errors)