Пример #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)
    client_dir = client_id_dir(client_id)
    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)
  
    status = returnvalues.OK
  
    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Job Manager'
    title_entry['style'] = css_tmpl(configuration)
    title_entry['javascript'] = js_tmpl()
  
    output_objects.append({'object_type': 'header', 'text': 'Job Manager'})
    output_objects.append({'object_type': 'html_form', 'text': html_pre()})
    output_objects.append({'object_type': 'table_pager', 'entry_name': 'jobs',
                           'default_entries': default_pager_entries,
                           'form_append': pager_append()})
    output_objects.append({'object_type': 'html_form', 'text': html_post()})
  
    return (output_objects, status)
Пример #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)
    output_objects.append({"object_type": "header", "text": "%s Virtual Desktop" % configuration.short_title})
    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)

    title_entry = find_entry(output_objects, "title")
    title_entry["text"] = "Virtual Machines"

    if not configuration.site_enable_vmachines:
        output_objects.append(
            {
                "object_type": "text",
                "text": """Virtual machines are disabled on this site.
Please contact the Grid admins %s if you think they should be enabled.
"""
                % configuration.admin_email,
            }
        )
        return (output_objects, returnvalues.OK)

    settings_dict = load_settings(client_id, configuration)
    if not settings_dict or not settings_dict.has_key("VNCDISPLAY"):
        logger.info("Settings dict does not have VNCDISPLAY key - using default")
        (vnc_display_width, vnc_display_height) = (1024, 768)
    else:
        (vnc_display_width, vnc_display_height) = settings_dict["VNCDISPLAY"]

    # Make room for vnc control menu

    vnc_menu_height = 24
    vnc_display_height += vnc_menu_height
    password = vms.vnc_jobid(accepted["job_id"][0])

    # Do an "intoN" then map to acsii

    output_objects.append(
        {
            "object_type": "html_form",
            "text": vms.popup_snippet()
            + vms.vnc_applet(configuration, vnc_display_width, vnc_display_height, password),
        }
    )

    return (output_objects, status)
Пример #3
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)

    user_dir = os.path.join(configuration.user_home, 
                            client_id_dir(client_id))

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'ARC Queues'
    output_objects.append({'object_type': 'header', 'text'
                          : 'Available ARC queues'})

    if not configuration.site_enable_griddk:
        output_objects.append({'object_type': 'text', 'text':
                               '''Grid.dk features are disabled on this site.
Please contact the Grid admins %s if you think they should be enabled.
''' % configuration.admin_email})
        return (output_objects, returnvalues.OK)

    # could factor out from here, to be usable from outside
    if not configuration.arc_clusters:
        output_objects.append({'object_type': 'error_text', 'text':
                               'No ARC support!'})
        return (output_objects, returnvalues.ERROR)
    try:
        session = arc.Ui(user_dir)
        queues = session.getQueues()

    except arc.NoProxyError, err:
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'Error while retrieving: %s' % err.what()
                              })
        output_objects += arc.askProxy()
        return (output_objects, returnvalues.ERROR)
Пример #4
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]
    output_objects.append({'object_type': 'header', 'text'
                          : 'Show runtime environment details'})
    (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)
    re_name = accepted['re_name'][-1]

    if not valid_dir_input(configuration.re_home, re_name):
        logger.warning(
            "possible illegal directory traversal attempt re_name '%s'"
            % re_name)
        output_objects.append({'object_type': 'error_text', 'text'
                               : 'Illegal runtime environment name: "%s"'
                               % re_name})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if not is_runtime_environment(re_name, configuration):
        output_objects.append({'object_type': 'error_text', 'text'
                               : "'%s' is not an existing runtime environment!"
                               % re_name})
        return (output_objects, returnvalues.CLIENT_ERROR)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Runtime environment details'

    (re_dict, msg) = get_re_dict(re_name, configuration)
    if not re_dict:
        output_objects.append({'object_type': 'error_text', 'text'
                               : 'Could not read details for "%s"' % msg})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    output_objects.append(build_reitem_object(configuration, re_dict))

    return (output_objects, returnvalues.OK) 
Пример #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)
    client_dir = client_id_dir(client_id)
    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)
    
    status = returnvalues.OK

    all_paths = accepted['path']
    entry_path = all_paths[-1]
    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'File Manager'
    title_entry['style'] = css_tmpl(configuration)
    if 'submitjob' in extract_menu(configuration, title_entry):
        enable_submit = 'true'
    else:
        enable_submit = 'false'
    title_entry['javascript'] = js_tmpl(entry_path, enable_submit,
                                        str(configuration.site_enable_preview))
    
    output_objects.append({'object_type': 'header', 'text': 'File Manager' })
    output_objects.append({'object_type': 'html_form', 'text':
                           html_tmpl(configuration, title_entry)})

    if len(all_paths) > 1:
        output_objects.append({'object_type': 'sectionheader', 'text':
                               'All requested paths:'})
        for path in all_paths:
            output_objects.append({'object_type': 'link', 'text': path,
                                   'destination': 'fileman.py?path=%s' % path})
            output_objects.append({'object_type': 'text', 'text': ''})

    return (output_objects, status)
Пример #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)

    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)
    allowed_vgrids = user_allowed_vgrids(configuration, client_id)

    for visible_res_name in resource_list:
        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,
                                                      allowed_vgrids)
        output_objects.append(res_item)
        
    return (output_objects, status)
Пример #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)

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

    output_objects.append({'object_type': 'warning', 'text'
                          : '''
Remember that sending a membership or ownership request
generates a message to the owners of the target. All requests are 
logged together with the ID of the submitter. Spamming and other abuse
will not be tolerated!'''})

    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Request %s membership/ownership' % \
                           configuration.site_vgrid_label})
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<form method='post' action='sendrequestaction.py'>
<table align='center'>
<tr><td>Request type</td><td><select name=request_type>
<option value=vgridmember>%(_label)s membership</option>
<option value=vgridowner>%(_label)s ownership</option>
</select></td></tr>
<tr><td>
%(_label)s name </td><td><input name=vgrid_name />
</td></tr>
<tr>
<td>Reason (text to owners)</td><td><input name=request_text size=40 /></td>
</tr>
<tr><td><input type='submit' value='Submit' /></td><td></td></tr></table>
</form>""" % {'_label': configuration.site_vgrid_label}})

    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Request resource ownership'})
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<form method='post' action='sendrequestaction.py'>
<table align='center'>
<tr><td>Request type</td><td><select name=request_type>
<option value=resourceowner>Resource ownership</option>
</select></td></tr>
<tr><td>
Resource ID </td><td><input name=unique_resource_name />
</td></tr>
<tr>
<td>Reason (text to owners)</td><td><input name=request_text size=40 /></td>
</tr>
<tr><td><input type='submit' value='Submit' /></td><td></td></tr></table>
</form>"""})

    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Send message'})
    protocol_options = ''
    for proto in [any_protocol] + configuration.notify_protocols:
        protocol_options += '<option value=%s>%s</option>\n' % (proto, proto)
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<form method='post' action='sendrequestaction.py'>
<table align='center'>
<tr><td>Request type</td><td><select name=request_type>
<option value=plain>Plain message</option>
</select></td></tr>
<tr><td>
User ID </td><td><input name=cert_id size=50 />
</td></tr>
<tr><td>Protocol</td><td><select name=protocol>
%s
</select></td></tr>
<tr>
<td>Message</td>
<td><textarea name=request_text cols=72 rows=10 /></textarea></td>
</tr>
<tr><td><input type='submit' value='Send' /></td><td></td></tr></table>
</form>""" % protocol_options})

    return (output_objects, returnvalues.OK)
Пример #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)
    client_dir = client_id_dir(client_id)
    defaults = signature()[1]
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
        )

    # TODO: if validator is too tight we should accept rejects here
    #   and then make sure that such rejected fields are never printed

    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)
    path = accepted['path'][-1]
    current_dir = accepted['current_dir'][-1]

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

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

    # the client can choose to specify the path of the target directory with
    # current_dir + "/" + path, instead of specifying the complete path in
    # subdirs. This is usefull from ls.py where a hidden html control makes it
    # possible to target the directory from the current dir.

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s file web editor' % configuration.short_title
    title_entry['style'] = advanced_editor_css_deps()
    title_entry['javascript'] = advanced_editor_js_deps()
    title_entry['javascript'] += lock_info('this file', -1)
    output_objects.append({'object_type': 'header', 'text'
                          : 'Editing file in %s home directory' % \
                            configuration.short_title })

    if not path:
        now = time.gmtime()
        path = 'noname-%s.txt' % time.strftime('%d%m%y-%H%M%S', now)
        output_objects.append({'object_type': 'text', 'text'
                              : 'No path supplied - creating new file in %s'
                               % path})

    path = os.path.normpath(current_dir + path)
    real_path = os.path.abspath(base_dir + current_dir + path)
    if not valid_user_path(real_path, base_dir):
        logger.warning('%s tried to %s restricted path %s ! (%s)'
                       % (client_id, op_name, real_path, path))
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : "Invalid path! (%s expands to an illegal path)" % path})
        return (output_objects, returnvalues.CLIENT_ERROR)

    (owner, time_left) = acquire_edit_lock(real_path, client_id)
    if owner == client_id:
        javascript = \
            '''<script type="text/javascript">
setTimeout("newcountdown('%s', %d)", 1)
</script>
'''\
             % (path, time_left / 60)
        output_objects.append({'object_type': 'html_form', 'text'
                              : javascript})

        html = edit_file(path, real_path)
        output_objects.append({'object_type': 'html_form', 'text'
                              : html})
    else:
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : '%s acquired the editing lock for %s! (timeout in %d seconds)'
             % (owner, path, time_left)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    return (output_objects, returnvalues.OK)
Пример #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, op_menu=False)
    defaults = signature(configuration)[1]
    (validate_status, accepted) = validate_input(user_arguments_dict,
            defaults, output_objects, allow_rejects=False)
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    valid_show = get_valid_topics(configuration)
    if keyword_all in accepted['show']:
        show = valid_show.keys()
    else:
        show = [i.lower() for i in accepted['show'] if i.lower() in valid_show]
    if not show:
        logger.info('%s showing default topics' % op_name)
        show = defaults['show']
    openid_error = ', '.join(accepted['modauthopenid.error'])

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s login selector' % configuration.short_title
    # TODO: move ping to shared location for signup and login
    # TODO: wrap openid ping in function and split up for each oid
    title_entry['javascript'] = '''
<script type="text/javascript" src="/images/js/jquery.js"></script>
<script type="text/javascript" src="/images/js/jquery.migtools.js"></script>
<script type="text/javascript">
    $(document).ready(function() {
        var action = "login", oid_title, oid_url, tag_prefix;
        oid_title = "KIT";
        oid_url = "https://openid.ku.dk/id/";
        tag_prefix = "kitoid_";
        check_oid_available(action, oid_title, oid_url, tag_prefix);
        oid_title = "%s";
        var oid_url = "https://%s:%s/openid/id/";
        tag_prefix = "migoid_";
        check_oid_available(action, oid_title, oid_url, tag_prefix);
    });
</script>
''' % (configuration.short_title, configuration.user_openid_show_address,
       configuration.user_openid_show_port)
    title_entry['skipmenu'] = True
    header_entry = {'object_type': 'header', 'text'
                    : 'Welcome to the %s login selector page' % \
                    configuration.short_title}
    output_objects.append(header_entry)

    html = ""
    if openid_error:
        err_txt, report_txt = '', ''
        if 'no_idp_found' in openid_error:
            err_txt += "OpenID server did not respond!"
            report_txt += """It appears the requested OpenID login service is
offline"""
        else:
            err_txt += "OpenID server error!"
            report_txt += """It appears there's a problem with the requested
OpenID login service"""
        report_txt += """, so you cannot currently use it for login to %s.<br />
Please report the problem to your OpenID identity provider.
""" % configuration.short_title
        html += """<h2>OpenID Login to %s Failed!</h2>
<div class='errortext'>
%s (error code(s): %s)
</div>
<div class='warningtext'>
%s
</div>
""" % (configuration.short_title, err_txt, openid_error, report_txt)
    html += """<h2>Login to %s</h2>
<p>
There are multiple login methods as described below.
</p>
""" % configuration.short_title
    if configuration.user_openid_providers and 'kitoid' in show or \
           'migoid' in show:
        html += """<h2>OpenID</h2>
The simplest login method is to use an existing OpenID login if you have one.
"""
        if 'kitoid' in show:
            html += """
<p>
If you are a KU user, your usual login for KU Net and KU webmail works for
OpenID as well.
</p>
<div id='kitoid_status'>
<!-- OpenID status updated by AJAX call -->
</div>
<div id='kitoid_debug'>
<!-- OpenID debug updated by AJAX call -->
</div>
<div class='form_container'>
<form method='post' action='%(kitoid_url)s'>
<input id='kitoid_button' type='submit' value='Login with KU OpenID' />
</form>
</div>
"""
        if 'migoid' in show:
            html += """
<p>
If you already have a MiG OpenID account here you can login to the account
using the local MiG OpenID server.
<div id='migoid_status'>
<!-- OpenID status updated by AJAX call -->
</div>
<div id='migoid_debug'>
<!-- OpenID debug updated by AJAX call -->
</div>
<div class='form_container'>
<form method='post' action='%(migoid_url)s'>
<input id='migoid_button' type='submit' value='Login with MiG OpenID' />
</form>
</p>
</div>
"""
            
        html += """
<p>
When you click the Login with OpenID button you will be taken to a login
page, where you need to provide your credentials and accept that your identity
is used for login with this site.
</p>
"""

    if 'extcert' in show:
        html += """
<h2>Client Certificate</h2>
<p>
We provide high security access control with client certificates, like the ones
you may know from digital signature providers.
</p>
"""
        html += """
<p>
If you have an x509 user certificate associated with your account you can login
using it here.
Depending on your certificate installation you may be prompted for a password.
</p>
<div class='form_container'>
<form method='get' action='%(extcert_url)s'>
<input id='reqcert_button' type='submit' value='Login with Your User Certificate' />
</form>
</div>
"""
        html += """
"""
    var_map = {'kitoid_url': valid_show['kitoid']['url'],
               'migoid_url':valid_show['migoid']['url'],
               'extcert_url': valid_show['extcert']['url'],
               }
    output_objects.append({'object_type': 'html_form', 'text': html % var_map})
    return (output_objects, returnvalues.OK)
Пример #10
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)
Пример #11
0
        for name in os.listdir(res_dir):
            file_path = os.path.join(res_dir, name)
            if os.path.isfile(file_path):
                os.unlink(file_path)
    except Exception, err:
        output_objects.append({'object_type': 'error_text', 'text'
                               : 'Deletion exception: ' + str(err)})
        output_objects.append({'object_type': 'link', 'destination':
                               'resman.py', 'class': 'infolink', 'title':
                               'Show resources', 'text': 'Show resources'})
        lock_handle_vgrid.close()
        lock_handle_res.close()
        return (output_objects, returnvalues.CLIENT_ERROR)

    # The resource has been deleted, and OK is returned.
    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Resource Deletion'
    output_objects.append({'object_type': 'header', 'text'
                          : 'Deleting resource'})
    output_objects.append({'object_type': 'text', 'text'
                           : 'Sucessfully deleted resource: ' + resource_id})
    output_objects.append({'object_type': 'link', 'destination': 'resman.py',
                           'class': 'infolink', 'title': 'Show resources',
                           'text': 'Show resources'})
    
    # Releasing locks
    lock_handle_vgrid.close()
    lock_handle_res.close()

    # Remove resource from resource and vgrid caches (after realeasing locks)
    unmap_resource(configuration, resource_id)
Пример #12
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'] = "Reject %s Request" % label
    output_objects.append({
        'object_type': 'header',
        'text': 'Reject %s Request' % label
    })
    (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)

    vgrid_name = accepted['vgrid_name'][-1].strip()
    request_name = unhexlify(accepted['request_name'][-1])

    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)

    # Validity of user and vgrid names is checked in this init function so
    # no need to worry about illegal directory traversal through variables

    (ret_val, msg, ret_variables) = \
        init_vgrid_script_add_rem(vgrid_name, client_id, request_name,
                                  'request', configuration)
    if not ret_val:
        output_objects.append({'object_type': 'error_text', 'text': msg})
        return (output_objects, returnvalues.CLIENT_ERROR)
    elif msg:

        # In case of warnings, msg is non-empty while ret_val remains True

        output_objects.append({'object_type': 'warning', 'text': msg})

    if request_name:
        request_dir = os.path.join(configuration.vgrid_home, vgrid_name)
        req = load_access_request(configuration, request_dir, request_name)
    if not req or not delete_access_request(configuration, request_dir,
                                            request_name):
        logger.error("failed to delete owner request for %s in %s" % \
                     (vgrid_name, request_name))
        output_objects.append({
            'object_type': 'error_text', 'text':
            'Failed to remove saved vgrid request for %s in %s!'\
            % (vgrid_name, request_name)})
        return (output_objects, returnvalues.CLIENT_ERROR)
    output_objects.append({
        'object_type':
        'text',
        'text':
        '''
Deleted %(request_type)s access request to %(target)s for %(entity)s .
''' % req
    })
    if req['request_type'] == 'vgridresource':
        id_field = "unique_resource_name"
    else:
        id_field = "cert_id"
    form_method = 'post'
    csrf_limit = get_csrf_limit(configuration)
    fill_helpers = {
        'protocol': any_protocol,
        'id_field': id_field,
        'vgrid_label': label,
        'form_method': form_method,
        'csrf_field': csrf_field,
        'csrf_limit': csrf_limit
    }
    fill_helpers.update(req)
    target_op = 'sendrequestaction'
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    fill_helpers.update({'target_op': target_op, 'csrf_token': csrf_token})

    output_objects.append({
        'object_type':
        'html_form',
        'text':
        """
<p>
You can use the reply form below if you want to additionally send an
explanation for rejecting the request.
</p>
<form method='%(form_method)s' action='%(target_op)s.py'>
<input type='hidden' name='%(csrf_field)s' value='%(csrf_token)s' />
<input type=hidden name=request_type value='vgridreject' />
<input type=hidden name=vgrid_name value='%(target)s' />
<input type=hidden name=%(id_field)s value='%(entity)s' />
<input type=hidden name=protocol value='%(protocol)s' />
<table>
<tr>
<td class='title'>Optional reject message to requestor(s)</td>
</tr><tr>
<td><textarea name=request_text cols=72 rows=10>
We have decided to reject your %(request_type)s request to our %(target)s
%(vgrid_label)s.

Regards, the %(target)s %(vgrid_label)s owners
</textarea></td>
</tr>
<tr>
<td><input type='submit' value='Inform requestor(s)' /></td>
</tr>
</table>
</form>
<br />
""" % fill_helpers
    })
    output_objects.append({
        'object_type': 'link',
        'destination': 'adminvgrid.py?vgrid_name=%s' % vgrid_name,
        'text': 'Back to administration for %s' % vgrid_name
    })
    return (output_objects, returnvalues.OK)
Пример #13
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)
    client_dir = client_id_dir(client_id)
    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)

    width = accepted['width'][-1]
    height = accepted['height'][-1]
    depth = accepted['depth'][-1]
    desktopname = accepted['desktopname'][-1]

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

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

    status = returnvalues.OK

    add_init = '''
      function endVNC () {
      if (!window.XMLHttpRequest)
        var httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
      else
        var httpRequest = new XMLHttpRequest();
      try {
        httpRequest.open("POST", "vncstop.py", "");
        httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        httpRequest.send("");
	}
	catch (e) 
	{
	  alert(e);
	  return e;
        }
      }
    '''

    # ## TODO: Include something like the following for support for interactive jobrequests!
    # ===============================================================================
    #    function submitjob(request) {
    #    if (!window.XMLHttpRequest)
    #     var httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
    #    else
    #      var httpRequest = new XMLHttpRequest();
    #      try {
    #        httpRequest.open('POST', 'textarea.py', '');
    #        httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    #        httpRequest.send(request);
    #      }
    #      catch (e) {
    #        alert(e);
    #        return e;
    #      }
    #      if (httpRequest.status == 200)
    #        return httpRequest.responseText;
    #      else
    #        return httpRequest.status + " " + httpRequest.statusText;
    #    }
    # ##############################################################333
    # ....FOLLOWING IS A SAMPLE TAKEN FROM: dsl.gymer.dk (thx. for sharing gymer)
    # ....function submitkey() {
    # ....        var form = document.getElementById("submitkeyform");
    # ....        var res = submitjob("action=submitkey"+"&key="+form.key.value );
    # ....        document.getElementById("subcontent").innerHTML = res;
    # ....}
    # ===============================================================================

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s Interactive Session' % configuration.short_title
    title_entry['script']['init'] = add_init
    title_entry['script']['body'] = 'onUnLoad="endVNC()"'
    output_objects.append({
        'object_type': 'header',
        'text': 'Session for: %s' % client_id
    })

    error = ''

    # Find available port/display.
    # TODO: Separate port and display no... Check /tmp/.X11-lock/ for available displays
    # ....and make bind check for available ports! Display might be in use without
    # ....using a port and vice-versa!

    passwdfile = ''
    password = ''

    valid_display_found = False
    (stat, msg) = get_users_display_dict(client_id, configuration, logger)
    if stat == False:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Error getting dictionary of live displays %s' % msg
        })
        status = returnvalues.CLIENT_ERROR
        return (output_objects, status)
    if stat == -1:
        logger.info('no existing display number for %s - creating' % client_id)
        baseVNCport = configuration.job_vnc_ports[0]
        VNC_port_count = len(configuration.job_vnc_ports)
        display_number = 1
        start_display = 5

        for i in range(start_display, VNC_port_count + start_display):
            free_display_found = False
            try:
                S = socket.socket()
                S.bind(('', baseVNCport + i))
                display_number = i
                vnc_port = baseVNCport + display_number
                free_display_found = True
            except Exception, exc:
                error = exc
            S.close()
            S = None

            if free_display_found:

                # verify display is free or steal it? verify for now

                (disp_numb_stat, disp_numb_ret) = \
                    get_dict_from_display_number(i, configuration,
                                                 logger)
                if disp_numb_stat == False:
                    output_objects.append({
                        'object_type':
                        'error_text',
                        'text':
                        'Error getting dictionary for display %s' %
                        disp_numb_ret
                    })
                    status = returnvalues.CLIENT_ERROR
                    return (output_objects, status)
                if disp_numb_ret != -1:

                    # display is registered as being in use, but the display seems to be available.

                    continue
                else:

                    # display is available

                    (passstat, passmsg) = create_vnc_password()
                    if passstat == False:
                        output_objects.append({
                            'object_type': 'error_text',
                            'text': passmsg
                        })
                        status = returnvalues.CLIENT_ERROR
                        logger.error('%s' % passmsg)
                        return (output_objects, status)

                    (password, passwdfile) = passmsg

                    valid_display_found = True
                    (stat, msg) = set_user_display_active(
                        client_id,
                        display_number,
                        vnc_port,
                        password,
                        configuration,
                        logger,
                    )
                    if not stat:
                        output_objects.append({
                            'object_type':
                            'error_text',
                            'text':
                            'could not set user display active: %s' % msg
                        })
                        status = returnvalues.CLIENT_ERROR
                        return (output_objects, status)
                    break
Пример #14
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)
    client_dir = client_id_dir(client_id)
    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)

    flags = ''.join(accepted['flags'])
    dst = accepted['dst'][-1].lstrip(os.sep)
    pattern_list = accepted['src']

    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)

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

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

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Zip/tar archive extractor'
    output_objects.append({'object_type': 'header', 'text'
                          : 'Zip/tar archive extractor'})

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

    if 'h' in flags:
        usage(output_objects)

    # IMPORTANT: path must be expanded to abs for proper chrooting
    abs_dest = os.path.abspath(os.path.join(base_dir, dst))
    logger.info('unpack in %s' % abs_dest)

    # Don't use real dest in output as it may expose underlying
    # fs layout.

    relative_dest = abs_dest.replace(base_dir, '')
    if not valid_user_path(configuration, abs_dest, base_dir, True):

        # out of bounds

        logger.error('%s tried to %s restricted path %s ! (%s)'
                       % (client_id, op_name, abs_dest, dst))
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : "Invalid path! (%s expands to an illegal path)" % dst})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if not check_write_access(abs_dest, parent_dir=True):
        logger.warning('%s called without write access: %s' % \
                       (op_name, abs_dest))
        output_objects.append(
            {'object_type': 'error_text', 'text':
             'cannot unpack to "%s": inside a read-only location!' % \
             relative_dest})
        return (output_objects, returnvalues.CLIENT_ERROR)

    status = returnvalues.OK

    for pattern in pattern_list:

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

        unfiltered_match = glob.glob(base_dir + pattern)
        match = []
        for server_path in unfiltered_match:
            # IMPORTANT: path must be expanded to abs for proper chrooting
            abs_path = os.path.abspath(server_path)
            if not valid_user_path(configuration, abs_path, base_dir, True):
                logger.warning('%s tried to %s restricted path %s ! (%s)'
                               % (client_id, op_name, abs_path, pattern))
                continue
            match.append(abs_path)

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

        if not match:
            output_objects.append({'object_type': 'file_not_found',
                                  'name': pattern})
            status = returnvalues.FILE_NOT_FOUND

        for abs_path in match:
            relative_path = abs_path.replace(base_dir, '')
            if verbose(flags):
                output_objects.append({'object_type': 'file', 'name'
                                       : relative_path})
            (unpack_status, msg) = unpack_archive(configuration,
                                                  client_id,
                                                  relative_path,
                                                  relative_dest)
            if not unpack_status:
                output_objects.append({'object_type': 'error_text',
                                       'text': 'Error: %s' % msg})
                status = returnvalues.CLIENT_ERROR
                continue
            output_objects.append(
                {'object_type': 'text', 'text'
                 : 'The zip/tar archive %s was unpacked in %s'
                 % (relative_path, relative_dest)})

    return (output_objects, status)
Пример #15
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)
    action = accepted['action'][-1]
    req_list = accepted['req_id']
    job_list = accepted['job_id']
    lines = int(accepted['lines'][-1])

    meta = '''<meta http-equiv="refresh" content="%s" />
''' % configuration.sleep_secs
    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s administration panel' % configuration.short_title
    title_entry['meta'] = meta

    # jquery support for tablesorter and confirmation on "remove"
    # table initially sorted by col. 9 (created)

    table_spec = {'table_id': 'accountreqtable', 'sort_order': '[[9,0]]'}
    (add_import, add_init, add_ready) = man_base_js(configuration,
                                                    [table_spec])
    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)
    })

    if not is_admin(client_id, configuration, logger):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'You must be an admin to access this control panel.'
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    html = ''
    if action and not action in grid_actions.keys() + accountreq_actions:
        output_objects.append({
            'object_type': 'error_text',
            'text': 'Invalid action: %s' % action
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)
    if action in grid_actions:
        msg = "%s" % grid_actions[action]
        if job_list:
            msg += ' %s' % ' '.join(job_list)
        msg += '\n'
        if not send_message_to_grid_script(msg, logger, configuration):
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                '''Error sending %s message to grid_script.''' % action
            })
            status = returnvalues.SYSTEM_ERROR
    elif action in accountreq_actions:
        if action == "addaccountreq":
            for req_id in req_list:
                if accept_account_req(req_id, configuration):
                    output_objects.append({
                        'object_type':
                        'text',
                        'text':
                        'Accepted account request %s' % req_id
                    })
                else:
                    output_objects.append({
                        'object_type':
                        'error_text',
                        'text':
                        'Accept account request failed - details in log'
                    })
        elif action == "delaccountreq":
            for req_id in req_list:
                if delete_account_req(req_id, configuration):
                    output_objects.append({
                        'object_type':
                        'text',
                        'text':
                        'Deleted account request %s' % req_id
                    })
                else:
                    output_objects.append({
                        'object_type':
                        'error_text',
                        'text':
                        'Delete account request failed - details in log'
                    })

    show, drop = '', ''
    general = """
<h2>Server Status</h2>
<p class='importanttext'>
This page automatically refreshes every %s seconds.
</p>
<p>
You can see the current grid daemon status and server logs below. The buttons
provide access to e.g. managing the grid job queues.
</p>
<form method='get' action='migadmin.py'>
    <input type='hidden' name='action' value='' />
    <input type='submit' value='Show last log lines' />
    <input type='text' size='2' name='lines' value='%s' />
</form>
<br />
<form method='get' action='migadmin.py'>
    <input type='hidden' name='lines' value='%s' />
    <input type='hidden' name='action' value='reloadconfig' />
    <input type='submit' value='Reload Configuration' />
</form>
<br />
""" % (configuration.sleep_secs, lines, lines)
    show += """
<form method='get' action='migadmin.py'>
    <input type='hidden' name='lines' value='%s' />
    <input type='submit' value='Log Jobs' />
    <select name='action'>
""" % lines
    drop += """
<form method='get' action='migadmin.py'>
    <input type='hidden' name='lines' value='%s' />
    <input type='submit' value='Drop Job' />
    <select name='action'>
""" % lines
    for queue in ['queued', 'executing', 'done']:
        selected = ''
        if action.find(queue) != -1:
            selected = 'selected'
        show += "<option %s value='show%s'>%s</option>" % (selected, queue,
                                                           queue)
        drop += "<option %s value='drop%s'>%s</option>" % (selected, queue,
                                                           queue)
    show += """
    </select>
</form>
<br />
"""
    drop += """
    </select>
    <input type='text' size='20' name='job_id' value='' />
</form>
<br />
"""
    html += general
    html += show
    html += drop

    daemons = """
<div id='daemonstatus'>
"""
    daemon_names = []
    if configuration.site_enable_jobs:
        daemon_names += ['grid_script.py', 'grid_monitor.py', 'grid_sshmux.py']
    if configuration.site_enable_events:
        daemon_names.append('grid_events.py')
    # No need to run im_notify unless any im notify protocols are enabled
    if configuration.site_enable_imnotify and \
            [i for i in configuration.notify_protocols if i != 'email']:
        daemon_names.append('grid_imnotify.py')
    if configuration.site_enable_sftp:
        daemon_names.append('grid_sftp.py')
    if configuration.site_enable_davs:
        daemon_names.append('grid_webdavs.py')
    if configuration.site_enable_ftps:
        daemon_names.append('grid_ftps.py')
    if configuration.site_enable_openid:
        daemon_names.append('grid_openid.py')
    if configuration.site_enable_transfers:
        daemon_names.append('grid_transfers.py')
    if configuration.site_enable_crontab:
        daemon_names.append('grid_cron.py')
    if configuration.site_enable_seafile:
        daemon_names += [
            'seafile-controller', 'seaf-server', 'ccnet-server', 'seahub'
        ]
        if configuration.seafile_mount:
            daemon_names.append('seaf-fuse')
    if configuration.site_enable_sftp_subsys:
        daemon_names.append(
            '/sbin/sshd -f /etc/ssh/sshd_config-MiG-sftp-subsys')
    for proc in daemon_names:
        # NOTE: we use command list here to avoid shell requirement
        pgrep_proc = subprocess_popen(['pgrep', '-f', proc],
                                      stdout=subprocess_pipe,
                                      stderr=subprocess_stdout)
        pgrep_proc.wait()
        ps_out = pgrep_proc.stdout.read().strip()
        if pgrep_proc.returncode == 0:
            daemons += "<div class='status_online'>%s running (pid %s)</div>" \
                       % (proc, ps_out)
        else:
            daemons += "<div class='status_offline'>%s not running!</div>" % \
                       proc
    daemons += """</div>
<br />
"""
    html += daemons

    output_objects.append({
        'object_type': 'header',
        'text': 'Pending Certificate Requests'
    })

    (list_status, ret) = list_account_reqs(configuration)
    if not list_status:
        logger.error("%s: failed for '%s': %s" % (op_name, client_id, ret))
        output_objects.append({'object_type': 'error_text', 'text': ret})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    form_method = 'post'
    csrf_limit = get_csrf_limit(configuration)
    target_op = 'migadmin'
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    accountreqs = []
    for req_id in ret:
        (load_status, req_dict) = get_account_req(req_id, configuration)
        if not load_status:
            logger.error("%s: load failed for '%s': %s" %
                         (op_name, req_id, req_dict))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Could not read details for "%s"' % req_id
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)
        req_item = build_accountreqitem_object(configuration, req_dict)

        js_name = 'create%s' % req_id
        helper = html_post_helper(js_name, '%s.py' % target_op, {
            'action': 'addaccountreq',
            'req_id': req_id,
            csrf_field: csrf_token
        })
        output_objects.append({'object_type': 'html_form', 'text': helper})
        req_item['addaccountreqlink'] = {
            'object_type':
            'link',
            'destination':
            "javascript: confirmDialog(%s, '%s');" %
            (js_name, 'Really accept %s?' % req_id),
            'class':
            'addlink iconspace',
            'title':
            'Accept %s' % req_id,
            'text':
            ''
        }
        js_name = 'delete%s' % req_id
        helper = html_post_helper(js_name, '%s.py' % target_op, {
            'action': 'delaccountreq',
            'req_id': req_id,
            csrf_field: csrf_token
        })
        output_objects.append({'object_type': 'html_form', 'text': helper})
        req_item['delaccountreqlink'] = {
            'object_type':
            'link',
            'destination':
            "javascript: confirmDialog(%s, '%s');" %
            (js_name, 'Really remove %s?' % req_id),
            'class':
            'removelink iconspace',
            'title':
            'Remove %s' % req_id,
            'text':
            ''
        }
        accountreqs.append(req_item)

    output_objects.append({
        'object_type': 'table_pager',
        'entry_name': 'pending certificate/OpenID account requests',
        'default_entries': default_pager_entries
    })
    output_objects.append({
        'object_type': 'accountreqs',
        'accountreqs': accountreqs
    })

    log_path_list = []
    if os.path.isabs(configuration.logfile):
        log_path_list.append(configuration.logfile)
    else:
        log_path_list.append(
            os.path.join(configuration.log_dir, configuration.logfile))
    for log_path in log_path_list:
        html += '''
<h2>%s</h2>
<textarea class="fillwidth padspace" rows=%s readonly="readonly">
''' % (log_path, lines)
        log_lines = read_tail(log_path, lines, logger)
        html += ''.join(log_lines[-lines:])
        html += '''</textarea>
'''

    output_objects.append({'object_type': 'html_form', 'text': html})
    return (output_objects, returnvalues.OK)
Пример #16
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)

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

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Manage jobs'
    output_objects.append({'object_type': 'header', 'text': 'Manage Jobs'})
    output_objects.append({
        'object_type': 'sectionheader',
        'text': 'View status of all submitted jobs'
    })
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
<form method="get" action="jobstatus.py">
Sort by modification time: <input type="radio" name="flags" value="sv" />yes
<input type="radio" name="flags" checked="checked" value="vi" />no<br />
<input type="hidden" name="job_id" value="*" />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Show All" />
</form>
    '''
    })
    output_objects.append({
        'object_type': 'sectionheader',
        'text': 'View status of individual jobs'
    })
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
Filter job IDs (* and ? wildcards are supported)<br />
<form method="get" action="jobstatus.py">
Job ID: <input type="text" name="job_id" value="*" size="30" /><br />
Show only <input type="text" name="max_jobs" size="6" value=5 /> first matching jobs<br />
Sort by modification time: <input type="radio" name="flags" checked="checked" value="vsi" />yes
<input type="radio" name="flags" value="vi" />no<br />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Show" />
</form>
    '''
    })
    output_objects.append({
        'object_type': 'sectionheader',
        'text': 'Resubmit job'
    })
    form_method = 'post'
    csrf_limit = get_csrf_limit(configuration)
    fill_helpers = {
        'short_title': configuration.short_title,
        'form_method': form_method,
        'csrf_field': csrf_field,
        'csrf_limit': csrf_limit
    }
    target_op = 'resubmit'
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    fill_helpers.update({'target_op': target_op, 'csrf_token': csrf_token})
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
<form method="%(form_method)s" action="%(target_op)s.py">
<input type="hidden" name="%(csrf_field)s" value="%(csrf_token)s" />
Job ID: <input type="text" name="job_id" size="30" /><br />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Submit" />
</form>
    ''' % fill_helpers
    })
    output_objects.append({
        'object_type': 'sectionheader',
        'text': 'Freeze pending job'
    })
    target_op = 'jobaction'
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    fill_helpers.update({'target_op': target_op, 'csrf_token': csrf_token})
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
<form method="%(form_method)s" action="%(target_op)s.py">
<input type="hidden" name="%(csrf_field)s" value="%(csrf_token)s" />
Job ID: <input type="text" name="job_id" size="30" /><br />
<input type="hidden" name="action" value="freeze" />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Freeze job" />
</form>
    ''' % fill_helpers
    })
    output_objects.append({
        'object_type': 'sectionheader',
        'text': 'Thaw frozen job'
    })
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
<form method="%(form_method)s" action="%(target_op)s.py">
<input type="hidden" name="%(csrf_field)s" value="%(csrf_token)s" />
Job ID: <input type="text" name="job_id" size="30" /><br />
<input type="hidden" name="action" value="thaw" />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Thaw job" />
</form>
    ''' % fill_helpers
    })
    output_objects.append({
        'object_type': 'sectionheader',
        'text': 'Cancel pending or executing job'
    })
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
<form method="%(form_method)s" action="%(target_op)s.py">
<input type="hidden" name="%(csrf_field)s" value="%(csrf_token)s" />
Job ID: <input type="text" name="job_id" size="30" /><br />
<input type="hidden" name="action" value="cancel" />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Cancel job" />
</form>
    ''' % fill_helpers
    })
    output_objects.append({
        'object_type': 'sectionheader',
        'text': 'Request live I/O'
    })
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
<form method="get" action="liveio.py">
Job ID: <input type="text" name="job_id" size="30" /><br />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Request" />
</form>
<br />
    '''
    })
    return (output_objects, status)
Пример #17
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)
Пример #18
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)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Advanced Shell'
    if accepted['menu'][-1] == 'no':
        title_entry['skipmenu'] = True
        title_entry['skipwidgets'] = True
        title_entry['style'] = '''
<style type="text/css">
#content { margin: 10px }
</style>'''
    # Please have href points to the CSS file and have basedir changed to the
    # directory where JavaScripts are placed.
    title_entry['style'] += '''
<link rel="stylesheet" type="text/css" href="/images/css/shell.css" media="screen"/>
'''
    title_entry['javascript'] = '''
<script type="text/javascript">
  var  basedir="/images/js/";

  var shell;
  var interval;
  // scripts have to be loaded in sequence, thereby this recursion.
  var scripts=["toolkits.js","gui.js","ajax.js","intellisense.js",
               "output.js","status.js","lib.js","shell.js"];
  function loadAll(s_i) {
        if(s_i<1)
        {
            shell=new Shell('shell', 'shell', 'xmlrpcinterface.py');
            shell.Init();
            return;
        }
        var script=document.createElement('script');
        script.setAttribute('type','text/javascript');
        script.setAttribute('src',basedir + scripts[ scripts.length - s_i ]);
        document.getElementsByTagName('head')[0].appendChild(script);

        if ( script.readyState ) {
           // IE style browser
           script.onreadystatechange= function () {
                if(this.readyState=='loaded'||this.readyState=='complete')
                    loadAll( s_i-1 );
            }
        } else {
        // other browser, should support onload
            script.onload=function()
            {
                loadAll( s_i-1 );
            }
        }
        return;
    }
</script>
'''
#    title_entry['bodyfunctions']='onload="mkShell();"'
    title_entry['bodyfunctions']='onload="loadAll(scripts.length);"'
    
    output_objects.append({'object_type': 'header', 'text': 'Advanced Shell'
                          })
    output_objects.append({'object_type': 'html_form', 'text'
                          :'<div id="shell"><!-- filled by js --></div>'})

    return (output_objects, status)
Пример #19
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)
    output_objects.append({'object_type': 'header', 'text':
                           '%s Request Virtual Machine' % \
                           configuration.short_title})
    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)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Virtual Machines'

    if not configuration.site_enable_vmachines:
        output_objects.append({'object_type': 'text', 'text':
                               '''Virtual machines are disabled on this site.
Please contact the Grid admins %s if you think they should be enabled.
''' % configuration.admin_email})
        return (output_objects, returnvalues.OK)

    build_form = '''
<form method="post" action="vmachines.py">
<input type="hidden" name="output_format" value="html">
<input type="hidden" name="action" value="create">

<table style="margin: 0px; width: 100%;">
<tr>
  <td style="width: 20%;">Machine name</td>
  <td>
  <input type="text" name="machine_name" size="30" value="MyVirtualDesktop">
  </td>
</tr>
</table>

<fieldset>
<legend><input type="radio" name="machine_type" value="pre" checked="checked">Prebuilt</legend>
<table>
<tr>
  <td style="width: 20%;">Choose a OS version</td>
  <td>
  
<select name="os">
'''
    for os in vms.available_os_list(configuration):
        build_form += '<option value="%s">%s</option>\n' % \
                      (os, os.capitalize())
    build_form += '''
</select>

  </td>
</tr>
<tr>
  <td>Choose a machine image</td>
  <td>
  
<select name="flavor">
'''
    for flavor in vms.available_flavor_list(configuration):
        build_form += '<option value="%s">%s</option>\n' % \
                      (flavor, flavor.capitalize())
    build_form += """
</select>

  </td>
</tr>
<tr>
  <td>Select a runtime environment providing the chosen OS and
flavor combination.
For Ubuntu systems you can typically just use a runtime env from the same year,
like VBOX3.1-IMAGES-2010-1 for ubuntu-10.* versions.</td>
  <td>
  
<input type="hidden" name="hypervisor_re" value="%s">
<select name="sys_re">
""" % configuration.vm_default_hypervisor_re
    for sys_re in vms.available_sys_re_list(configuration):
        build_form += '<option value="%s">%s</option>\n' % \
                      (sys_re, sys_re)
    build_form += '''
</select>

  </td>
</tr>
</table>

</fieldset>

<fieldset>
<legend><input type="radio" name="machine_type" value="custom" disabled>Custom:</legend>
<span class="warningtext">Custom builds are currently unavailable.</span>
<table>
<tr>
  <td style="width: 20%;">Software</td>
  <td>
<input type=text size=80 name="machine_software" readonly
value="iptables acpid x11vnc xorg gdm xfce4 gcc make netsurf python-openssl" />
  </td>
</tr>
</table>

</fieldset>
<input type="submit" value="Submit machine request!">

</form>
'''
    output_objects.append({'object_type': 'html_form', 'text': build_form})
    return (output_objects, status)
Пример #20
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)
Пример #21
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)

    vgrid_name = accepted['vgrid_name'][-1]

    # prepare support for confirm dialog and toggling the views (by css/jquery)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = "Administrate %s: %s" % \
                          (configuration.site_vgrid_label, vgrid_name)

    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': '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'
                          : "Administrate '%s'" % vgrid_name })

    if not vgrid_is_owner(vgrid_name, client_id, configuration):
        output_objects.append({'object_type': 'error_text', 'text': 
                    'Only owners of %s can administrate it.' % vgrid_name })
        js_name = 'reqvgridowner%s' % hexlify(vgrid_name)
        helper = html_post_helper(js_name, 'sendrequestaction.py',
                                  {'vgrid_name': vgrid_name,
                                   'request_type': 'vgridowner',
                                   'request_text': ''})
        output_objects.append({'object_type': 'html_form', 'text': helper})
        output_objects.append(
            {'object_type': 'link',
             'destination':
             "javascript: confirmDialog(%s, '%s', '%s');"\
             % (js_name, "Request ownership of " + \
                vgrid_name + ":<br/>" + \
                "\nPlease write a message to the owners below.",
                'request_text'),
             'class': 'addadminlink',
             'title': 'Request ownership of %s' % vgrid_name,
             'text': 'Apply to become an owner'})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    for (item, scr) in zip(['owner', 'member', 'resource'],
                        ['vgridowner', 'vgridmember', 'vgridres']):
        output_objects.append({'object_type': 'sectionheader',
                               'text': "%ss" % item.title()
                               })
        if item == 'trigger':
            # Always run as rule creator to avoid users being able to act on
            # behalf of ANY other user using triggers (=exploit)
            extra_fields = [('path', None),
                            ('changes', [keyword_all] + valid_trigger_changes),
                            ('run_as', client_id),
                            ('action', [keyword_auto] + valid_trigger_actions),
                            ('arguments', None)]
        else:
            extra_fields = []

        (status, oobjs) = vgrid_add_remove_table(client_id, vgrid_name, item, 
                                                 scr, configuration,
                                                 extra_fields)
        if not status:
            output_objects.extend(oobjs)
            return (output_objects, returnvalues.SYSTEM_ERROR)
        else:
            output_objects.append({'object_type': 'html_form', 
                                   'text': '<div class="div-%s">' % item })
            output_objects.append(
                {'object_type': 'link', 
                 'destination': 
                 "javascript:toggleHidden('.div-%s');" % item,
                 'class': 'removeitemlink',
                 'title': 'Toggle view',
                 'text': 'Hide %ss' % item.title() })
            output_objects.extend(oobjs)
            output_objects.append(
                {'object_type': 'html_form', 
                 'text': '</div><div class="hidden div-%s">' % item})
            output_objects.append(
                {'object_type': 'link', 
                 'destination': 
                 "javascript:toggleHidden('.div-%s');" % item,
                 'class': 'additemlink',
                 'title': 'Toggle view',
                 'text': 'Show %ss' % item.title() })
            output_objects.append({'object_type': 'html_form', 
                                   'text': '</div>' })

    # Checking/fixing of missing components

    output_objects.append({'object_type': 'sectionheader',
                           'text': "Repair/Add Components"})
    output_objects.append({'object_type': 'html_form',
                           'text': '''
      <form method="post" action="updatevgrid.py">
          <input type="hidden" name="vgrid_name" value="%(vgrid)s" />
          <input type="submit" value="Repair components" />
      </form>
''' % {'vgrid': vgrid_name}})

    output_objects.append({'object_type': 'sectionheader',
                           'text': "Delete %s " % vgrid_name})
    output_objects.append({'object_type': 'html_form',
                           'text': '''
To delete <b>%(vgrid)s</b> remove all members and owners ending with yourself.
''' % {'vgrid': vgrid_name}})

    return (output_objects, returnvalues.OK)
Пример #22
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'] = 'Delete runtime environment'
    output_objects.append({
        'object_type': 'header',
        'text': 'Delete runtime environment'
    })
    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)

    re_name = accepted['re_name'][-1]

    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)

    if not valid_dir_input(configuration.re_home, re_name):
        logger.warning(
            "possible illegal directory traversal attempt re_name '%s'" %
            re_name)
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Illegal runtime environment name: "%s"' % re_name
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Check whether re_name represents a runtime environment
    if not is_runtime_environment(re_name, configuration):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            "No such runtime environment: '%s'" % re_name
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    (re_dict, load_msg) = get_re_dict(re_name, configuration)
    if not re_dict:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Could not read runtime environment details for %s: %s' %
            (re_name, load_msg)
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # Make sure the runtime environment belongs to the user trying to delete it
    if client_id != re_dict['CREATOR']:
        output_objects.append({'object_type': 'error_text', 'text': \
        'You are not the owner of runtime environment "%s"' % re_name})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Prevent delete if the runtime environment is used by any resources
    actives = resources_using_re(configuration, re_name)

    # If the runtime environment is active, an error message is printed, along
    # with a list of the resources using the runtime environment
    if actives:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            "Can't delete runtime environment '%s' in use by resources:" %
            re_name
        })
        output_objects.append({'object_type': 'list', 'list': actives})
        output_objects.append({
            'object_type': 'link',
            'destination': 'redb.py',
            'class': 'infolink iconspace',
            'title': 'Show runtime environments',
            'text': 'Show runtime environments'
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Delete the runtime environment
    (del_status, msg) = delete_runtimeenv(re_name, configuration)

    # If something goes wrong when trying to delete runtime environment
    # re_name, an error is displayed.
    if not del_status:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Could not remove %s runtime environment: %s' % (re_name, msg)
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # If deletion of runtime environment re_name is successful, we just
    # return OK
    else:
        output_objects.append({
            'object_type':
            'text',
            'text':
            'Successfully deleted runtime environment: "%s"' % re_name
        })
        output_objects.append({
            'object_type': 'link',
            'destination': 'redb.py',
            'class': 'infolink iconspace',
            'title': 'Show runtime environments',
            'text': 'Show runtime environments'
        })
        return (output_objects, returnvalues.OK)
Пример #23
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)
Пример #24
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, op_menu=False)
    defaults = signature()[1]
    (validate_status, accepted) = validate_input(user_arguments_dict,
                                                 defaults,
                                                 output_objects,
                                                 allow_rejects=False)
    if not validate_status:
        logger.warning('%s invalid input: %s' % (op_name, accepted))
        return (accepted, returnvalues.CLIENT_ERROR)

    if not 'migcert' in configuration.site_signup_methods:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''X.509 certificate login is not enabled on this site'''
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

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

    admin_email = configuration.admin_email
    smtp_server = configuration.smtp_server
    user_pending = os.path.abspath(configuration.user_pending)

    # force name to capitalized form (henrik karlsen -> Henrik Karlsen)
    # please note that we get utf8 coded bytes here and title() treats such
    # chars as word termination. Temporarily force to unicode.

    raw_name = accepted['cert_name'][-1].strip()
    try:
        cert_name = force_utf8(force_unicode(raw_name).title())
    except Exception:
        cert_name = raw_name.title()
    country = accepted['country'][-1].strip().upper()
    state = accepted['state'][-1].strip().title()
    org = accepted['org'][-1].strip()

    # lower case email address

    email = accepted['email'][-1].strip().lower()
    password = accepted['password'][-1]
    verifypassword = accepted['verifypassword'][-1]

    # keep comment to a single line

    comment = accepted['comment'][-1].replace('\n', '   ')

    # single quotes break command line format - remove

    comment = comment.replace("'", ' ')

    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)

    if password != verifypassword:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Password and verify password are not identical!'
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    try:
        assure_password_strength(configuration, password)
    except Exception, exc:
        logger.warning(
            "%s invalid password for '%s' (policy %s): %s" %
            (op_name, cert_name, configuration.site_password_policy, exc))
        output_objects.append({
            'object_type': 'error_text',
            'text': 'Invalid password requested: %s.' % exc
        })
        output_objects.append({
            'object_type': 'link',
            'destination': 'javascript:history.back();',
            'class': 'genericbutton',
            'text': "Try again"
        })
        return (output_objects, returnvalues.CLIENT_ERROR)
Пример #25
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)

    flavor = accepted['flavor'][-1].strip()

    if not flavor in freeze_flavors.keys():
        output_objects.append({'object_type': 'error_text', 'text':
                           'Invalid freeze flavor: %s' % flavor})
        return (output_objects, returnvalues.CLIENT_ERROR)

    title = freeze_flavors[flavor]['adminfreeze_title']
    output_objects.append({'object_type': 'header', 'text': title})
    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = title

    if not configuration.site_enable_freeze:
        output_objects.append({'object_type': 'text', 'text':
                               '''Freezing archives is disabled on this site.
Please contact the Grid admins %s if you think it should be enabled.
''' % configuration.admin_email})
        return (output_objects, returnvalues.OK)

    # jquery support for dynamic addition of copy/upload fields

    title_entry['style'] = themed_styles(configuration,
                                         base=['jquery.contextmenu.css',
                                               'jquery.xbreadcrumbs.css',
                                               'jquery.fmbreadcrumbs.css',
                                               'jquery.fileupload.css',
                                               'jquery.fileupload-ui.css'],
                                         skin=['fileupload-ui.custom.css',
                                               'xbreadcrumbs.custom.css'])
    title_entry['javascript'] = '''
<script type="text/javascript" src="/images/js/jquery.js"></script>
<script type="text/javascript" src="/images/js/jquery-ui.js"></script>
<!-- Filemanager and dependencies -->
<script type="text/javascript" src="/images/js/jquery.form.js"></script>
<script type="text/javascript" src="/images/js/jquery.prettyprint.js"></script>
<script type="text/javascript" src="/images/js/jquery.filemanager.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.contextmenu.js"></script>
<script type="text/javascript" src="/images/js/jquery.xbreadcrumbs.js"></script>
<!-- The preview image plugin -->
<script type="text/javascript" src="/images/js/preview.js"></script>
<!-- The image manipulation CamanJS plugin used by the preview image plugin -->
<script type="text/javascript" src="/images/lib/CamanJS/dist/caman.full.js"></script>
<script type="text/javascript">
       Caman.DEBUG = false
</script>
<!-- The nouislider plugin used by the preview image plugin -->
<script type="text/javascript" src="/images/lib/noUiSlider/jquery.nouislider.all.js"></script>

<!-- Fancy file uploader and dependencies -->
<!-- The Templates plugin is included to render the upload/download listings -->
<script type="text/javascript" src="/images/js/tmpl.min.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
<script type="text/javascript" src="/images/js/load-image.min.js"></script>
<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
<script type="text/javascript" src="/images/js/jquery.iframe-transport.js"></script>
<!-- The basic File Upload plugin -->
<script type="text/javascript" src="/images/js/jquery.fileupload.js"></script>
<!-- The File Upload processing plugin -->
<script type="text/javascript" src="/images/js/jquery.fileupload-process.js"></script>
<!-- The File Upload image preview & resize plugin -->
<script type="text/javascript" src="/images/js/jquery.fileupload-image.js"></script>
<!-- The File Upload validation plugin -->
<script type="text/javascript" src="/images/js/jquery.fileupload-validate.js"></script>
<!-- The File Upload user interface plugin -->
<script type="text/javascript" src="/images/js/jquery.fileupload-ui.js"></script>
<!-- The File Upload jQuery UI plugin -->
<script type="text/javascript" src="/images/js/jquery.fileupload-jquery-ui.js"></script>

<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% console.log("using upload template"); %}
{% console.log("... with upload files: "+$.fn.dump(o)); %}
{% var dest_dir = "./" + $("#fancyfileuploaddest").val(); %}
{% console.log("using upload dest: "+dest_dir); %}
{% for (var i=0, file; file=o.files[i]; i++) { %}
    {% var rel_path = $.fn.normalizePath(dest_dir+"/"+file.name); %}
    {% console.log("using upload rel_path: "+rel_path); %}
    <tr class="template-upload fade">
        <td>
            <span class="preview"></span>
        </td>
        <td>
            <p class="name">{%=rel_path%}</p>
            <strong class="error"></strong>
        </td>
        <td>
            <div class="size pending">Processing...</div>
            <div class="progress"></div>
        </td>
        <td>
            {% if (!i && !o.options.autoUpload) { %}
                <button class="start" disabled>Start</button>
            {% } %}
            {% if (!i) { %}
                <button class="cancel">Cancel</button>
            {% } %}
        </td>
    </tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% console.log("using download template"); %}
{% console.log("... with download files: "+$.fn.dump(o)); %}
{% for (var i=0, file; file=o.files[i]; i++) { %}
    {% var rel_path = $.fn.normalizePath("./"+file.name); %}
    {% console.log("using download rel_path: "+rel_path); %}
    <tr class="template-download fade">
        <td>
            <span class="preview">
                {% if (file.thumbnailUrl) { %}
                <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
                {% } %}
            </span>
        </td>
        <td>
            <p class="name">
                <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?\'data-gallery\':\'\'%}>{%=rel_path%}</a>
            </p>
            {% if (file.error) { %}
                <div><span class="error">Error</span> {%=file.error%}</div>
            {% } %}
        </td>
        <td>
            <div class="size">{%=o.formatFileSize(file.size)%}</div>
        </td>
        <td>
            <button class="delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields=\'{"withCredentials":true}\'{% } %}>{% if (file.deleteUrl) { %}Delete{% } else { %}Dismiss{% } %}</button>
            <input type="checkbox" name="delete" value="1" class="toggle">
        </td>
    </tr>
{% } %}
</script>

<script type="text/javascript" >

var copy_fields = 0;
var upload_fields = 0;
var open_file_chooser;
var open_upload_dialog;
'''
    title_entry['javascript'] += '''
/* default upload destination */
var remote_path = "%s";
''' % upload_tmp_dir
    title_entry['javascript'] += '''
function add_copy(div_id) {
    var field_id = "freeze_copy_"+copy_fields;
    var field_name = "freeze_copy_"+copy_fields;
    var wrap_id = field_id+"_wrap";
    var browse_id = field_id+"_browse";
    copy_entry = "<span id=\'"+wrap_id+"\'>";
    copy_entry += "<input type=\'button\' value=\'Remove\' ";
    copy_entry += " onClick=\'remove_field(\"+wrap_id+\");\'/>";
    // add browse button to mimic upload field
    copy_entry += "<input type=\'button\' id=\'"+browse_id+"\' ";
    copy_entry += " value=\'Browse...\' />";
    copy_entry += "<input type=\'text\' id=\'"+field_id+"\' ";
    copy_entry += " name=\'" + field_name + "\' size=80 /><br / >";
    copy_entry += "</span>";

    $("#"+div_id).append(copy_entry);
    $("#"+field_id).click(function() {
        open_file_chooser("Add file or directory (right click to select)",
            function(file) {
                $("#"+field_id).val(file);
            });
    });
    $("#"+browse_id).click(function() {
         $("#"+field_id).click();
    });
    $("#"+field_id).click();
    copy_fields += 1;
}

function add_upload(div_id) {
    var field_id, field_name, wrap_id, path, on_remove;
    open_upload_dialog("Upload Files", function() {
            console.log("in upload callback");
            $(".uploadfileslist > tr > td > p.name > a").each(
                function(index) {
                    console.log("callback for upload item no. "+index);
                    path = $(this).text();
                    if ($(this).attr("href") == "") {
                        console.log("skipping empty (error) upload: "+path);
                        // Continue to next iteration on errors
                        return true;
                    }
                    console.log("callback for upload path "+path);
                    field_id = "freeze_move_"+upload_fields;
                    field_name = "freeze_move_"+upload_fields;
                    wrap_id = field_id+"_wrap";
                    if ($("#"+div_id+" > span > input[value=\'"+path+"\']").length) {
                        console.log("skipping duplicate path: "+path);
                        // Continue to next iteration on errors
                        return true;
                    } else {
                        console.log("adding new path: "+path);
                    }
                    on_remove = "";
                    on_remove += "remove_field("+wrap_id+");";
                    on_remove += "$.fn.delete_upload(\\""+path+"\\");";
                    upload_entry = "<span id=\'"+wrap_id+"\'>";
                    upload_entry += "<input type=\'button\' value=\'Remove\' ";
                    upload_entry += " onClick=\'"+on_remove+"\'/>";
                    upload_entry += "<input type=\'text\' id=\'"+field_id+"\' ";
                    upload_entry += " name=\'" + field_name + "\' size=50 ";
                    upload_entry += "value=\'"+path+"\' /><br / >";
                    upload_entry += "</span>";
                    $("#"+div_id).append(upload_entry);
                    console.log("callback added upload: "+upload_entry);
                    upload_fields += 1;
                });
            console.log("callback done");
        }, remote_path, true);
}

function remove_field(field_id) {
    $(field_id).remove();
}

// init file chooser dialogs with directory selction support
function init_dialogs() {
    open_file_chooser = mig_filechooser_init("fm_filechooser",
        function(file) {
            return;
        }, false, "/");
    open_upload_dialog = mig_fancyuploadchunked_init("fancyuploadchunked_dialog");

    $("#addfilebutton").click(function() { add_copy(\"copyfiles\"); });
    $("#adduploadbutton").click(function() { add_upload(\"uploadfiles\"); });
}

function init_page() {
    init_dialogs();
}

$(document).ready(function() {
         // do sequenced initialisation (separate function)
         init_page();
     }
);
</script>
'''

    shared_files_form = """
<!-- and now this... we do not want to see it, except in a dialog: -->
<div id='fm_filechooser' style='display:none'>
    <div class='fm_path_breadcrumbs'>
        <ul id='fm_xbreadcrumbs' class='xbreadcrumbs'>
        </ul>
    </div>
    <div class='fm_addressbar'>
        <input type='hidden' value='/' name='fm_current_path' />
    </div>
    <div class='fm_folders'>
        <ul class='jqueryFileTree'>
            <li class='directory expanded'>
                <a>...</a>
            </li>
        </ul>
    </div>
    <div class='fm_files'>
        <table id='fm_filelisting' style='font-size:13px; border-spacing=0;'>
            <thead>
                <tr>
                    <th>Name</th>
                    <th style='width: 80px;'>Size</th>
                    <th style='width: 50px;'>Type</th>
                    <th style='width: 120px;'>Date Modified</th>
                </tr>
            </thead>
            <tbody>
                <!-- this is a placeholder for contents: do not remove! -->
            </tbody>
         </table>     
    </div>
    <div id='fm_statusbar'>
        <div id='fm_statusprogress'><div class='progress-label'>Loading...</div></div>
        <div id='fm_statusinfo'>&nbsp;</div>
    </div>
    <div id='fm_options'><input id='fm_touchscreen' type='checkbox'>
    Enable touch screen interface (all clicks trigger menu)
    <input id='fm_dotfiles' type='checkbox'>
    Show hidden files and dirs
    </div>
</div>
<div id='cmd_dialog' title='Command output' style='display: none;'></div>

<div id='fancyuploadchunked_dialog' title='Upload File' style='display: none;'>

    <!-- The file upload form used as target for the file upload widget -->
    <form id='fancyfileupload' action='uploadchunked.py?output_format=json;action=put'
        method='POST' enctype='multipart/form-data'>
        <fieldset id='fancyfileuploaddestbox'>
            <label id='fancyfileuploaddestlabel' for='fancyfileuploaddest'>
                Optional final destination dir:
            </label>
            <input id='fancyfileuploaddest' type='text' size=60 value=''>
        </fieldset>

        <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
        <div class='fileupload-buttonbar'>
            <div class='fileupload-buttons'>
                <!-- The fileinput-button span is used to style the file input field as button -->
                <span class='fileinput-button'>
                    <span>Add files...</span>
                    <input type='file' name='files[]' multiple>
                </span>
                <button type='submit' class='start'>Start upload</button>
                <button type='reset' class='cancel'>Cancel upload</button>
                <button type='button' class='delete'>Delete</button>
                <input type='checkbox' class='toggle'>
                <!-- The global file processing state -->
                <span class='fileupload-process'></span>
            </div>
            <!-- The global progress state -->
            <div class='fileupload-progress fade' style='display:none'>
                <!-- The global progress bar -->
                <div class='progress' role='progressbar' aria-valuemin='0' aria-valuemax='100'></div>
                <!-- The extended global progress state -->
                <div class='progress-extended'>&nbsp;</div>
            </div>
        </div>
        <!-- The table listing the files available for upload/download -->
        <table role='presentation' class='table table-striped'><tbody class='uploadfileslist'></tbody></table>
    </form>
    <!-- For status and error output messages -->
    <div id='fancyuploadchunked_output'></div>
</div>
    """

    if flavor == 'freeze':
        intro_text = """
Please enter your archive details below and select any files to be included in
the archive.
<p class='warn_message'>Note that a frozen archive can not be changed after
creation and it can only be manually removed by the management, so please be
careful when filling in the details.
</p>
"""
        files_form = shared_files_form
        freeze_form = """
<form enctype='multipart/form-data' method='post' action='createfreeze.py'>
<b>Name:</b><br />
<input type='hidden' name='flavor' value='freeze' />
<input type='text' name='freeze_name' size=30 autofocus />
<input type='hidden' name='freeze_author' value='UNSET' />
<input type='hidden' name='freeze_department' value='UNSET' />
<input type='hidden' name='freeze_organization' value='UNSET' />
<br /><b>Description:</b><br />
<textarea cols='80' rows='20' name='freeze_description'></textarea>
<br />
<br />
<div id='freezefiles'>
<b>Freeze Archive Files:</b>
<input type='button' id='addfilebutton' value='Add file/directory' />
<input type='button' id='adduploadbutton' value='Add upload' />
<div id='copyfiles'>
<!-- Dynamically filled -->
</div>
<div id='uploadfiles'>
<!-- Dynamically filled -->
</div>
</div>
<br />
<div id='freezepublish'>
<input type='checkbox' name='freeze_publish' />
<b>Make Dataset Publicly Available</b>
</div>
<br />
<input type='submit' value='Create Archive' />
</form>
"""
    if flavor == 'phd':
        intro_text = """
Please enter your PhD details below and select any files associated with your
thesis.
<p class='warn_message'>Note that a thesis archive can not be changed after
creation and it can only be manually removed by the management, so please be
careful when filling in the details.
</p>
"""
        files_form = shared_files_form
        freeze_form = """
<form enctype='multipart/form-data' method='post' action='createfreeze.py'>
<b>Thesis Title:</b><br />
<input type='hidden' name='flavor' value='phd' />
<input type='hidden' name='freeze_organization' value='UNSET' />
<input type='text' name='freeze_name' size=80 />
<br /><b>Author Name:</b><br />
<input type='text' name='freeze_author' size=40 />
<br /><b>Department:</b><br />
<input type='text' name='freeze_department' size=40 />
<br />
<br />
<div id='freezefiles'>
<b>Thesis and Associated Files to Archive:</b>
<input type='button' id='addfilebutton' value='Add file/directory' />
<input type='button' id='adduploadbutton' value='Add upload' />
<div id='copyfiles'>
<!-- Dynamically filled -->
</div>
<div id='uploadfiles'>
<!-- Dynamically filled -->
</div>
</div>
<br />
<div id='freezepublish'>
<input type='checkbox' name='freeze_publish' />
<b>Make Dataset Publicly Available</b>
</div>
<br /><b>Dataset Description:</b><br />
<textarea cols='80' rows='20' name='freeze_description'></textarea>
<br />
<br />
<input type='submit' value='Archive Thesis' />
</form>
"""

    output_objects.append({'object_type': 'html_form', 'text': intro_text})
    output_objects.append({'object_type': 'html_form', 'text': files_form})
    output_objects.append({'object_type': 'html_form', 'text': freeze_form})

    return (output_objects, returnvalues.OK)
Пример #26
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')
    title_entry['text'] = 'People'
    (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)

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

    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 "send"
        # table initially sorted by 0 (name)

        # NOTE: We distinguish between caching on page load and forced refresh
        refresh_helper = 'ajax_people(%s, %%s)'
        refresh_call = refresh_helper % configuration.notify_protocols
        table_spec = {'table_id': 'usertable', 'sort_order': '[[0,0]]',
                      'refresh_call': refresh_call % 'false'}
        (add_import, add_init, add_ready) = man_base_js(configuration,
                                                        [table_spec],
                                                        {'width': 640})
        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': 'People'})

        output_objects.append(
            {'object_type': 'text', 'text':
             'View and communicate with other users.'
             })

        output_objects.append(
            {'object_type': 'sectionheader', 'text': 'All users'})

        # Helper form for sends

        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('sendmsg', '%s.py' % target_op,
                                  {'cert_id': '__DYNAMIC__',
                                   'protocol': '__DYNAMIC__',
                                   'request_type': 'plain',
                                   'request_text': '',
                                   csrf_field: csrf_token})
        output_objects.append({'object_type': 'html_form', 'text':
                               helper})

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

    users = []
    if operation in list_operations:
        logger.info("get vgrid and user map with caching %s" % caching)
        visible_user = user_visible_user_confs(configuration, client_id,
                                               caching)
        vgrid_access = user_vgrid_access(configuration, client_id,
                                         caching=caching)
        anon_map = anon_to_real_user_map(configuration)
        if not visible_user:
            output_objects.append(
                {'object_type': 'error_text', 'text': 'no users found!'})
            return (output_objects, returnvalues.SYSTEM_ERROR)

        if caching:
            modified_users, _ = check_users_modified(configuration)
            modified_vgrids, _ = check_vgrids_modified(configuration)
            if modified_users:
                logger.info("pending user cache updates: %s" % modified_users)
                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")

        for (visible_user_id, user_dict) in visible_user.items():
            user_id = visible_user_id
            if visible_user_id in anon_map.keys():
                # Maintain user anonymity
                pretty_id = 'Anonymous user with unique ID %s' % visible_user_id
                user_id = anon_map[visible_user_id]
            else:
                # Show user-friendly version of user ID
                hide_email = user_dict.get(CONF, {}).get('HIDE_EMAIL_ADDRESS',
                                                         True)
                pretty_id = pretty_format_user(user_id, hide_email)
            user_obj = {'object_type': 'user', 'name': visible_user_id,
                        'pretty_id': pretty_id}
            user_obj.update(user_dict)
            # NOTE: datetime is not json-serializable so we force to string
            created = user_obj.get(CONF, {}).get('CREATED_TIMESTAMP', '')
            if created:
                user_obj[CONF]['CREATED_TIMESTAMP'] = str(created)
            user_obj['userdetailslink'] = \
                {'object_type': 'link',
                 'destination':
                 'viewuser.py?cert_id=%s'
                 % quote(visible_user_id),
                 'class': 'infolink iconspace',
                 'title': 'View details for %s' %
                 visible_user_id,
                 'text': ''}
            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)
            for proto in configuration.notify_protocols:
                if not email_vgrids and proto == 'email':
                    continue
                if not im_vgrids and proto != 'email':
                    continue
                if user_obj[CONF].get(proto.upper(), None):
                    link = 'send%slink' % proto
                    user_obj[link] = {
                        'object_type': 'link',
                        'destination':
                        "javascript: confirmDialog(%s, '%s', '%s', %s);"
                        % ('sendmsg', 'Really send %s message to %s?'
                           % (proto, visible_user_id),
                           'request_text',
                           "{cert_id: '%s', 'protocol': '%s'}" %
                           (visible_user_id, proto)),
                        'class': "%s iconspace" % link,
                        'title': 'Send %s message to %s' %
                        (proto, visible_user_id),
                        'text': ''}
            logger.debug("append user %s" % user_obj)
            users.append(user_obj)

    if operation == "show":
        # insert dummy placeholder to build table
        user_obj = {'object_type': 'user', 'name': ''}
        users.append(user_obj)

    output_objects.append({'object_type': 'user_list',
                           'pending_updates': pending_updates,
                           'users': users})

    logger.info("%s %s end for %s" % (op_name, operation, client_id))
    return (output_objects, returnvalues.OK)
Пример #27
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)

    vgrid_name = accepted['vgrid_name'][-1]

    if not vgrid_is_owner_or_member(vgrid_name, client_id,
                                    configuration):
        output_objects.append({'object_type': 'error_text',
                              'text': '''You must be an owner or member of %s vgrid to
access the workflows.'''
                               % vgrid_name})
        return (output_objects, returnvalues.CLIENT_ERROR)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s Workflows' \
        % configuration.site_vgrid_label
    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">
$(document).ready(function() {

          $("#logarea").scrollTop($("#logarea")[0].scrollHeight);

          // table initially sorted by 0 (last update / date) 
          var sortOrder = [[0,1]];

          // 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;
          }

          $("#workflowstable").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="72" rows="10" id="confirm_input" style="display:none;"></textarea>
 </div>
'''})

    output_objects.append({'object_type': 'header',
                          'text': '%s Workflows for %s'
                          % (configuration.site_vgrid_label,
                          vgrid_name)})

    logger.info('vgridworkflows %s' % vgrid_name)

    # Display active trigger jobs for this vgrid

    output_objects.append({'object_type': 'sectionheader',
                          'text': 'Active Trigger Jobs'})
    html = '<table><thead><tr>'
    html += '<th>Job ID</th>'
    html += '<th>Rule</th>'
    html += '<th>Path</th>'
    html += '<th>Change</th>'
    html += '<th>Time</th>'
    html += '<th>Status</th>'
    html += '</tr></thead>'
    html += '<tbody>'

    trigger_job_dir = os.path.join(configuration.vgrid_home,
                                   os.path.join(vgrid_name, '.%s.jobs'
                                   % configuration.vgrid_triggers))
    trigger_job_pending_dir = os.path.join(trigger_job_dir,
            'pending_states')
    trigger_job_final_dir = os.path.join(trigger_job_dir, 'final_states'
            )

    if makedirs_rec(trigger_job_pending_dir, logger) \
        and makedirs_rec(trigger_job_final_dir, logger):
        abs_vgrid_dir = '%s/' \
            % os.path.abspath(os.path.join(configuration.vgrid_files_home,
                              vgrid_name))
        for filename in os.listdir(trigger_job_pending_dir):
            trigger_job_filepath = \
                os.path.join(trigger_job_pending_dir, filename)
            trigger_job = unpickle(trigger_job_filepath, logger)
            serverjob_filepath = \
                os.path.join(configuration.mrsl_files_dir,
                             os.path.join(client_id_dir(trigger_job['owner'
                             ]), '%s.mRSL' % trigger_job['jobid']))
            serverjob = unpickle(serverjob_filepath, logger)
            if serverjob:
                if serverjob['STATUS'] in pending_states:
                    trigger_event = trigger_job['event']
                    trigger_rule = trigger_job['rule']
                    trigger_action = trigger_event['event_type']
                    trigger_time = time.ctime(trigger_event['time_stamp'
                            ])
                    trigger_path = '%s %s' % (trigger_event['src_path'
                            ].replace(abs_vgrid_dir, ''),
                            trigger_event['dest_path'
                            ].replace(abs_vgrid_dir, ''))
                    html += \
                        '<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></td><td>%s</td>' \
                        % (trigger_job['jobid'], trigger_rule['rule_id'
                           ], trigger_path, trigger_action, trigger_time,
                           serverjob['STATUS'])
                elif serverjob['STATUS'] in final_states:
                    src_path = os.path.join(trigger_job_pending_dir,
                            filename)
                    dest_path = os.path.join(trigger_job_final_dir,
                            filename)
                    move_file(src_path, dest_path, configuration)
                else:
                    logger.error('Trigger job: %s, unknown state: %s'
                                 % (trigger_job['jobid'],
                                 serverjob['STATUS']))
    html += '</tbody>'
    html += '</table>'
    output_objects.append({'object_type': 'html_form', 'text': html})

    # Display active trigger jobs for this vgrid

    output_objects.append({'object_type': 'sectionheader',
                          'text': 'Trigger Log'})
    log_content = read_trigger_log(configuration, vgrid_name)
    output_objects.append({'object_type': 'html_form',
                          'text': '''
 <div class="form_container">
 <textarea id="logarea" rows=10 readonly="readonly">%s</textarea>
 </div>
 '''
                          % log_content})

    output_objects.append({'object_type': 'sectionheader',
                          'text': 'Manage Triggers'})

    # Always run as rule creator to avoid users being able to act on behalf
    # of ANY other user using triggers (=exploit)

    extra_fields = [
        ('path', None),
        ('match_dirs', ['False', 'True']),
        ('match_recursive', ['False', 'True']),
        ('changes', [keyword_all] + valid_trigger_changes),
        ('action', [keyword_auto] + valid_trigger_actions),
        ('arguments', None),
        ('run_as', client_id),
        ]

    # NOTE: we do NOT show saved template contents - see addvgridtriggers

    optional_fields = [('rate_limit', None), ('settle_time', None)]

    (status, oobjs) = vgrid_add_remove_table(
        client_id,
        vgrid_name,
        'trigger',
        'vgridtrigger',
        configuration,
        extra_fields,
        optional_fields,
        )
    output_objects.extend(oobjs)

    if not status:
        return (output_objects, returnvalues.SYSTEM_ERROR)

    return (output_objects, returnvalues.OK)
Пример #28
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)

    target_list = accepted['target']

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'List Scheduled Tasks'

    header_entry = {'object_type': 'header', 'text': 'Scheduled Tasks'}
    output_objects.append(header_entry)

    if not configuration.site_enable_crontab:
        output_objects.append({
            'object_type':
            'text',
            'text':
            '''
Scheduled tasks are disabled on this site.
Please contact the site admins %s if you think they should be enabled.
''' % configuration.admin_email
        })
        return (output_objects, returnvalues.OK)

    logger.info('%s from %s' % (op_name, client_id))
    #logger.debug('%s from %s: %s' % (op_name, client_id, accepted))

    # Include handy CSRF helpers for use in subsequent client crontab changes
    csrf_helpers = {'csrf_field': csrf_field}
    form_method = 'post'
    csrf_limit = get_csrf_limit(configuration)
    for target_op in ('addcrontab', 'rmcrontab', 'crontab'):
        csrf_helpers[target_op] = make_csrf_token(configuration, form_method,
                                                  target_op, client_id,
                                                  csrf_limit)
    crontab_listing = {
        'object_type': 'crontab_listing',
        'crontab': [],
        'atjobs': [],
        'csrf_helpers': csrf_helpers
    }
    if not target_list:
        output_objects.append({
            'object_type': 'error_text',
            'text': 'No at/cron target to list!'
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    if keyword_all in target_list or 'crontab' in target_list:
        crontab_contents = load_crontab(client_id, configuration)
        cronjobs = []
        for line in crontab_contents.split('\n'):
            # Skip comments and blank lines
            line = line.split('#', 1)[0].strip()
            if not line:
                continue
            cronjobs.append(line)
        crontab_listing['crontab'] = cronjobs

    if keyword_all in target_list or 'atjobs' in target_list:
        atjobs_contents = load_atjobs(client_id, configuration)

        atjobs = []
        for line in atjobs_contents.split('\n'):
            # Skip comments and blank lines
            line = line.split('#', 1)[0].strip()
            if not line:
                continue
            atjobs.append(line)
        crontab_listing['atjobs'] = atjobs

    output_objects.append(crontab_listing)

    return (output_objects, returnvalues.OK)
Пример #29
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)
    client_dir = client_id_dir(client_id)
    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)

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

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

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Settings'
    
    # prepare support for toggling the views (by css/jquery)

    title_entry['style'] = themed_styles(configuration)
    title_entry['style']['skin'] += '''
%s
''' % cm_css
    title_entry['javascript'] = '''
<script type="text/javascript" src="/images/js/jquery.js"></script>
<script type="text/javascript" src="/images/js/jquery-ui.js"></script>

%s

<script type="text/javascript" >

    var toggleHidden = function(classname) {
        // classname supposed to have a leading dot 
        $(classname).toggleClass("hidden");
    }

$(document).ready(function() {
     }
);
</script>
''' % cm_javascript

    valid_topics = ['general', 'style']
    active_menu = extract_menu(configuration, title_entry)
    if 'submitjob' in active_menu:
        valid_topics.append('job')
    if 'people' in active_menu:
        valid_topics.append('profile')
    if configuration.site_script_deps:
        valid_topics.append('widgets')
    if configuration.arc_clusters:
        valid_topics.append('arc')
    if configuration.site_enable_sftp:
        valid_topics.append('sftp')
    if configuration.site_enable_davs:
        valid_topics.append('webdavs')
    if configuration.site_enable_ftps:
        valid_topics.append('ftps')
    topics = accepted['topic']
    # Backwards compatibility
    if topics and topics[0] == 'ssh':
        topics[0] = 'sftp'
    topics = [i for i in topics if i in valid_topics]
    # Default to general if no valid topics given
    if not topics:
        topics.append(valid_topics[0])
    topic_titles = dict([(i, i.title()) for i in valid_topics])
    for (key, val) in [('sftp', 'SFTP'), ('webdavs', 'WebDAVS'),
                       ('ftps', 'FTPS')]:
        if key in valid_topics:
            topic_titles[key] = val
    output_objects.append({'object_type': 'header', 'text'
                          : 'Settings'})

    links = []
    for name in valid_topics:
        active_menu = ''
        if topics[0]  == name:
            active_menu = 'activebutton'
        links.append({'object_type': 'link', 
                      'destination': "settings.py?topic=%s" % name,
                      'class': '%ssettingslink settingsbutton %s' % \
                      (name, active_menu),
                      'title': 'Switch to %s settings' % topic_titles[name],
                      'text' : '%s' % topic_titles[name],
                      })

    output_objects.append({'object_type': 'multilinkline', 'links': links,
                           'sep': '  '})
    output_objects.append({'object_type': 'text', 'text': ''})

    # load current settings

    current_settings_dict = load_settings(client_id, configuration)
    if not current_settings_dict:

        # no current settings found

        current_settings_dict = {}

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

    if 'general' in topics:
        html = \
             '''
        <div id="settings">
        <form method="post" action="settingsaction.py">
        <table class="settings fixedlayout">
        <tr class="title"><td class="centertext">
        Select your %s settings
        </td></tr>
        <tr><td>
        </td></tr>
        <tr><td>
        <input type="hidden" name="topic" value="general" />
        Please note that if you want to set multiple values (e.g. addresses)
        in the same field, you must write each value on a separate line but
        without blank lines.
        </td></tr>
        <tr><td>
        </td></tr>
        ''' % configuration.short_title
        settings_entries = get_settings_specs()
        for (keyword, val) in settings_entries:
            if 'SUBMITUI' == keyword and \
                   'job' not in valid_topics:
                continue
            if 'notify' == val['Context'] and \
                   keyword.lower() not in configuration.notify_protocols:
                continue
            entry = \
                """
            <tr class='title'><td>
            %s
            </td></tr>
            <tr><td>
            %s
            </td></tr>
            <tr><td>
            """\
                 % (keyword.replace('_', ' ').title(), val['Description'])
            if val['Type'] == 'multiplestrings':
                try:

                    # get valid choices from conf. multiple selections

                    valid_choices = eval('configuration.%s' % keyword.lower())
                    current_choice = []
                    if current_settings_dict.has_key(keyword):
                        current_choice = current_settings_dict[keyword]

                    if len(valid_choices) > 0:
                        entry += '<div class="scrollselect">'
                        for choice in valid_choices:
                            selected = ''
                            if choice in current_choice:
                                selected = 'checked'
                            entry += '''
                <input type="checkbox" name="%s" %s value="%s">%s<br />''' % \
                            (keyword, selected, choice, choice)
                        entry += '</div>'
                    else:
                        entry = ''
                except:
                    # failed on evaluating configuration.%s

                    area = '''
                <textarea id="%s" cols=40 rows=1 name="%s">''' % \
                    (keyword, keyword)
                    if current_settings_dict.has_key(keyword):
                        area += '\n'.join(current_settings_dict[keyword])
                    area += '</textarea>'
                    entry += wrap_edit_area(keyword, area, general_edit,
                                            'BASIC')

            elif val['Type'] == 'string':

                # get valid choices from conf

                valid_choices = eval('configuration.%s' % keyword.lower())
                current_choice = ''
                if current_settings_dict.has_key(keyword):
                    current_choice = current_settings_dict[keyword]

                if len(valid_choices) > 0:
                    entry += '<select name="%s">' % keyword
                    for choice in valid_choices:
                        selected = ''
                        if choice == current_choice:
                            selected = 'selected'
                        entry += '<option %s value="%s">%s</option>'\
                             % (selected, choice, choice)
                    entry += '</select><br />'
                else:
                    entry = ''
            elif val['Type'] == 'boolean':
                current_choice = ''
                if current_settings_dict.has_key(keyword):
                    current_choice = current_settings_dict[keyword]
                entry += '<select name="%s">' % keyword
                for choice in (True, False):
                    selected = ''
                    if choice == current_choice:
                        selected = 'selected'
                    entry += '<option %s value="%s">%s</option>'\
                             % (selected, choice, choice)
                entry += '</select><br />'
            html += """%s
            </td></tr>
            """ % entry

        html += \
            """
        <tr><td>
        <input type="submit" value="Save General Settings" />
        </td></tr>
        </table>
        </form>
        </div>
        """
        output_objects.append({'object_type': 'html_form', 'text': html})

    if 'job' in topics:
        mrsl_path = os.path.join(base_dir, default_mrsl_filename)

        default_mrsl = get_default_mrsl(mrsl_path)
        html = \
        '''
<div id="defaultmrsl">
<form method="post" action="editfile.py">
<table class="defaultjob fixedlayout">
<tr class="title"><td class="centertext">
Default job on submit page
</td></tr>
<tr><td>
</td></tr>
<tr><td>
If you use the same fields and values in many of your jobs, you can save your
preferred job description here to always start out with that description on
your submit job page.
</td></tr>
<tr><td>
</td></tr>
<tr><td>
<input type="hidden" name="path" value="%(mrsl_template)s" />
<input type="hidden" name="newline" value="unix" />
'''
        keyword = "defaultjob"
        area = '''
<textarea id="%(keyword)s" cols=82 rows=25 name="editarea">
%(default_mrsl)s
</textarea>
'''
        html += wrap_edit_area(keyword, area, cm_options, 'BASIC')
        
        html += '''
</td></tr>
<tr><td>
<input type="submit" value="Save Job Template" />
</td></tr>
</table>
</form>
</div>
'''
        html = html % {
            'default_mrsl': default_mrsl,
            'mrsl_template': default_mrsl_filename,
            'site': configuration.short_title,
            'keyword': keyword
            }

        output_objects.append({'object_type': 'html_form', 'text': html})

    if 'style' in topics:
        css_path = os.path.join(base_dir, default_css_filename)
        default_css = get_default_css(css_path)
        html = \
             '''
<div id="defaultcss">
<form method="post" action="editfile.py">
<table class="defaultstyle fixedlayout">
<tr class="title"><td class="centertext">
Default CSS (style) for all pages
</td></tr>
<tr><td>
</td></tr>
<tr><td>
If you want to customize the look and feel of the %(site)s web interfaces you
can override default values here. If you leave the style file blank you will
just use the default style.<br />
You can copy paste from the available style file links below if you want to
override specific parts.<br />
<div class="warningtext">Please note that you can not save an empty style
file, but must at least leave a blank line to use defaults. Additionally some
errors in your style code may potentially cause severe corruption in your page
layouts, so it may be a good idea to keep another browser tab/window ready to
(re)move your .default.css file to restore the defaults while experimenting
here.
</div>
</td></tr>
<tr><td>
<a class="urllink" href="/images/default.css">default</a> ,
<a class="urllink" href="/images/bluesky.css">bluesky</a>
</td></tr>
<tr><td>
</td></tr>
<tr><td>
<input type="hidden" name="path" value="%(css_template)s" />
<input type="hidden" name="newline" value="unix" />
'''
        keyword = "defaultstyle"
        area = '''
<textarea id="%(keyword)s" cols=82 rows=25 min_len=1 name="editarea">
%(default_css)s
</textarea>
'''
        html += wrap_edit_area(keyword, area, style_edit)
        html += '''
</td></tr>
<tr><td>
<input type="submit" value="Save Style Settings" />
</td></tr>
</table>
</form>
</div>
'''
        html = html % {
            'default_css': default_css,
            'css_template': default_css_filename,
            'site': configuration.short_title,
            'keyword': keyword
            }

        output_objects.append({'object_type': 'html_form', 'text': html})

    if 'widgets' in topics:

        # load current widgets

        current_widgets_dict = load_widgets(client_id, configuration)
        if not current_widgets_dict:
            
            # no current widgets found
            
            current_widgets_dict = {}

        show_widgets = current_settings_dict.get('ENABLE_WIDGETS', True)
        if show_widgets:
            edit_widgets = '''You can simply copy/paste from the available
widget file links below if you want to reuse existing widgets.<br />
</td></tr>
<tr><td>
<a class="urllink" href="/images/widgets/hello-grid.app">hello grid</a>,
<a class="urllink" href="/images/widgets/simple-calendar.app">simple calendar</a>,
<a class="urllink" href="/images/widgets/calendar.app">calendar</a>,
<a class="urllink" href="/images/widgets/gcal.app">google calendar</a>,
<a class="urllink" href="/images/widgets/calculator.app">calculator</a>,
<a class="urllink" href="/images/widgets/localrss.app">local rss reader</a>,
<a class="urllink" href="/images/widgets/rss.app">rss reader</a>,
<a class="urllink" href="/images/widgets/clock.app">clock</a>,
<a class="urllink" href="/images/widgets/weather.app">weather</a>,
<a class="urllink" href="/images/widgets/progressbar.app">progress bar</a>,
<a class="urllink" href="/images/widgets/simple-move.app">simple-move</a>,
<a class="urllink" href="/images/widgets/portlets.app">portlets</a>,
<a class="urllink" href="/images/widgets/countdown.app">countdown</a>,
<a class="urllink" href="/images/widgets/sparkline.app">mini chart</a>,
<a class="urllink" href="/images/widgets/piechart.app">pie chart</a>,
<a class="urllink" href="/images/widgets/simple-jobmon.app">simple-jobmon</a>,
<a class="urllink" href="/images/widgets/cert-countdown.app">certificate countdown</a>,
<a class="urllink" href="/images/widgets/disk-use.app">disk use progress bar</a>,
<a class="urllink" href="/images/widgets/jobs-stats.app">jobs stats table</a>,
<a class="urllink" href="/images/widgets/jobs-stats-chart.app">jobs stats chart</a>,
<a class="urllink" href="/images/widgets/daily-wm-comic.app">Daily WulffMorgenthaler comic</a>,
<a class="urllink" href="/images/widgets/kunet-login.app">KUnet login</a>
<a class="urllink" href="/images/widgets/tdchotspot-login.app">TDC Hotspot login</a>
</td></tr>
<tr><td>
<div class="warningtext">Please note that the widgets parser is rather grumpy
so you may have to avoid blank lines in your widget code below. Additionally
any errors in your widgets code may cause severe corruption in your pages, so
it may be a good idea to keep another browser tab/window ready for emergency
disabling of widgets while experimenting here.</div> 
</td></tr>
<tr><td>
<input type="hidden" name="topic" value="widgets" />
</td></tr>
<tr><td>
'''
            
        html = \
             '''<div id="widgets">
<form method="post" action="settingsaction.py">
<table class="widgets fixedlayout">
<tr class="title"><td class="centertext">
Default user defined widgets for all pages
</td></tr>
<tr><td>
</td></tr>
<tr><td>
If you want to customize the look and feel of the %s web interfaces you can
add your own widgets here. If you leave the widgets blank you will just get
the default empty widget spaces.<br />
''' % configuration.short_title

        widgets_entries = get_widgets_specs()
        widgets_html = ''
        for (keyword, val) in widgets_entries:
            widgets_html += \
                """
            <tr class=title><td>
            %s
            </td></tr>
            <tr><td>
            %s
            </td></tr>
            <tr><td>
            """\
                 % (keyword.replace('_', ' ').title(), val['Description'])
            if val['Type'] == 'multiplestrings':
                try:

                    # get valid choices from conf. multiple selections

                    valid_choices = eval('configuration.%s' % keyword.lower())
                    current_choice = []
                    if current_widgets_dict.has_key(keyword):
                        current_choice = current_widgets_dict[keyword]

                    if len(valid_choices) > 0:
                        widgets_html += '<div class="scrollselect">'
                        for choice in valid_choices:
                            selected = ''
                            if choice in current_choice:
                                selected = 'checked'
                            widgets_html += '''
                    <input type="checkbox" name="%s" %s value="%s">%s<br />'''\
                            % (keyword, selected, choice, choice)
                        widgets_html += '</div>'
                except:
                    area = \
                         """<textarea id='%s' cols=78 rows=10 name='%s'>""" % \
                         (keyword, keyword)
                    if current_widgets_dict.has_key(keyword):
                        area += '\n'.join(current_widgets_dict[keyword])
                    area += '</textarea>'
                    widgets_html += wrap_edit_area(keyword, area, widgets_edit)

        if show_widgets:
            edit_widgets += '''
        %s
        <tr><td>
        <input type="submit" value="Save Widgets Settings" />
</td></tr>
''' % widgets_html
        else:
            edit_widgets = '''
<br/>
<div class="warningtext">
Widgets are disabled on your <em>General</em> settings page. Please enable
them there first if you want to customize your grid pages.
</div>
'''            
        html += \
             '''
%s
</table>
</form>
</div>
''' % edit_widgets
        output_objects.append({'object_type': 'html_form', 'text': html})

    if 'profile' in topics:

        # load current profile

        current_profile_dict = load_profile(client_id, configuration)
        if not current_profile_dict:
            
            # no current profile found
            
            current_profile_dict = {}

        (got_list, all_vgrids) = vgrid_list_vgrids(configuration)
        if not got_list:
            all_vgrids = []
        all_vgrids.append(any_vgrid)
        all_vgrids.sort()
        configuration.vgrids_allow_email = all_vgrids
        configuration.vgrids_allow_im = all_vgrids
        images = []
        for path in os.listdir(base_dir):
            real_path = os.path.join(base_dir, path)
            if os.path.splitext(path)[1].strip('.') in profile_img_extensions \
                   and os.path.getsize(real_path) < profile_img_max_kb*1024:
                images.append(path)
        configuration.public_image = images
        html = \
             '''
<div id="profile">
<form method="post" action="settingsaction.py">
<table class="profile fixedlayout">
<tr class="title"><td class="centertext">
Public profile information visible to other users.
</td></tr>
<tr><td>
</td></tr>
<tr><td>
If you want to let other users know more about you can add your own text here.
If you leave the text area blank you will just get the default empty profile
information.<br />
</td></tr>
<tr><td>
<div class="warningtext">Please note that the profile parser is rather grumpy
so you may have to avoid blank lines in your text below.
</div> 
</td></tr>
<tr><td>
<input type="hidden" name="topic" value="profile" />
</td></tr>
<tr><td>
'''

        profile_entries = get_profile_specs()
        for (keyword, val) in profile_entries:
            # Mask VGrid name if configured
            mask_title = keyword.replace(
                'VGRID', configuration.site_vgrid_label.upper())
            mask_desc = val['Description'].replace(
                'VGrid', configuration.site_vgrid_label)
            html += \
                """
            <tr class=title><td>
            %s
            </td></tr>
            <tr><td>
            %s
            </td></tr>
            <tr><td>
            """ % (mask_title.replace('_', ' ').title(),
                   html_escape(mask_desc))
            if val['Type'] == 'multiplestrings':
                try:

                    # get valid choices from conf. multiple selections

                    valid_choices = eval('configuration.%s' % keyword.lower())
                    current_choice = []
                    if current_profile_dict.has_key(keyword):
                        current_choice = current_profile_dict[keyword]

                    if len(valid_choices) > 0:
                        html += '<div class="scrollselect">'
                        for choice in valid_choices:
                            selected = ''
                            if choice in current_choice:
                                selected = 'checked'
                            html += '''
                <input type="checkbox" name="%s" %s value="%s">%s<br />''' % \
                            (keyword, selected, choice, choice)
                        html += '</div>'
                except:
                    area = \
                         """<textarea id='%s' cols=78 rows=10 name='%s'>""" % \
                         (keyword, keyword)
                    if current_profile_dict.has_key(keyword):
                        area += '\n'.join(current_profile_dict[keyword])
                    area += '</textarea>'
                    html += wrap_edit_area(keyword, area, profile_edit)
            elif val['Type'] == 'boolean':
                valid_choices = [True, False]
                current_choice = ''
                if current_profile_dict.has_key(keyword):
                    current_choice = current_profile_dict[keyword]

                if len(valid_choices) > 0:
                    html += '<select name="%s">' % keyword
                    for choice in valid_choices:
                        selected = ''
                        if choice == current_choice:
                            selected = 'selected'
                        html += '<option %s value="%s">%s</option>'\
                             % (selected, choice, choice)
                    html += '</select><br />'

        html += '''
        <tr><td>
        <input type="submit" value="Save Profile Settings" />
</td></tr>
</table>
</form>
</div>
'''
        output_objects.append({'object_type': 'html_form', 'text': html})

    if 'sftp' in topics:

        # load current ssh/sftp

        current_ssh_dict = load_ssh(client_id, configuration)
        if not current_ssh_dict:
            
            # no current ssh found
            
            current_ssh_dict = {}

        default_authkeys = current_ssh_dict.get('authkeys', '')
        default_authpassword = current_ssh_dict.get('authpassword', '')
        username = client_alias(client_id)
        if configuration.user_sftp_alias:
            username = extract_field(client_id, configuration.user_sftp_alias)
            create_alias_link(username, client_id, configuration.user_home)
        sftp_server = configuration.user_sftp_show_address
        sftp_port = configuration.user_sftp_show_port
        html = \
        '''
<div id="sshaccess">
<form method="post" action="settingsaction.py">
<table class="sshsettings fixedlayout">
<tr class="title"><td class="centertext">
SFTP access to your %(site)s account
</td></tr>
<tr><td>
</td></tr>
<tr><td>
You can configure SFTP login to your %(site)s account for efficient file
access. On Linux/UN*X it also allows transparent access through SSHFS.
<br/>
<h3>Login Details</h3>
<ul>
<li>Host <em>%(sftp_server)s</em></li>
<li>Port <em>%(sftp_port)s</em></li>
<li>Username <em>%(username)s</em></li>
<li>%(auth_methods)s <em>as you choose below</em></li>
</ul>
</td></tr>
<tr><td>
<input type="hidden" name="topic" value="sftp" />
<div class="div-sftp-client-notes hidden">
<a href="javascript:toggleHidden('.div-sftp-client-notes');"
    class="removeitemlink" title="Toggle view">
    Show less SFTP client details...</a>
<h3>Graphical SFTP access</h3>
The FireFTP plugin for Firefox is known to generally work for graphical
access to your %(site)s home over SFTP.
Enter the following values in the FireFTP Account Manager:
<pre>
Host %(sftp_server)s
Login %(username)s
Password YOUR_PASSWORD_HERE (passphrase if you configured public key access)
Security SFTP
Port %(sftp_port)s
Private Key ~/.mig/key.pem (if you configured public key access)
</pre>
other graphical clients may work as well.
<h3>Command line SFTP/SSHFS access on Linux/UN*X</h3>
Save something like the following lines in your local ~/.ssh/config
to avoid typing the full login details every time:<br />
<pre>
Host %(sftp_server)s
Hostname %(sftp_server)s
User %(username)s
Port %(sftp_port)s
IdentityFile ~/.mig/key.pem
</pre>
From then on you can use sftp and sshfs to access your %(site)s home:
<pre>
sftp %(sftp_server)s
</pre>
<pre>
sshfs %(sftp_server)s: mig-home -o uid=$(id -u) -o gid=$(id -g)
</pre>
You can also integrate with ordinary mounts by adding a line like:
<pre>
sshfs#%(username)s@%(sftp_server)s: /home/USER/mig-home fuse noauto,user,port=%(sftp_port)d 0 0
</pre>
to your /etc/fstab .
</div>
<div class="div-sftp-client-notes">
<a href="javascript:toggleHidden('.div-sftp-client-notes');"
    class="additemlink" title="Toggle view">Show more SFTP client details...
    </a>
</div>
'''
        
        keyword_keys = "authkeys"
        if 'publickey' in configuration.user_sftp_auth:
            html += '''
</td></tr>
<tr><td>
<h3>Authorized Public Keys</h3>
You can use any existing RSA key, or create a new one. If you signed up with a
x509 user certificate, you should also have received such a key.pem along with
your user certificate. In any case you need to save the contents of the
corresponding public key (X.pub) in the text area below, to be able to connect
with username and key as described in the Login Details.
<br/>
'''
            area = '''
<textarea id="%(keyword_keys)s" cols=82 rows=5 name="publickeys">
%(default_authkeys)s
</textarea>
'''
            html += wrap_edit_area(keyword_keys, area, ssh_edit, 'BASIC')
            html += '''
(leave empty to disable sftp access with public keys)
</td></tr>
'''
            
        keyword_password = "******"
        if 'password' in configuration.user_sftp_auth:

            # We only want a single password and a masked input field
            html += '''
<tr><td>
<h3>Authorized Password</h3>
Please enter and save your desired password in the text field below, to be able
to connect with username and password as described in the Login Details.
<br/>
<input type=password id="%(keyword_password)s" size=40 name="password"
value="%(default_authpassword)s" />
(leave empty to disable sftp access with password)
</td></tr>
'''
        
        html += '''
<tr><td>
<input type="submit" value="Save SFTP Settings" />
</td></tr>
'''
        
        html += '''
</table>
</form>
</div>
'''
        html = html % {
            'default_authkeys': default_authkeys,
            'default_authpassword': default_authpassword,
            'site': configuration.short_title,
            'keyword_keys': keyword_keys,
            'keyword_password': keyword_password,
            'username': username,
            'sftp_server': sftp_server,
            'sftp_port': sftp_port,
            'auth_methods': ' / '.join(configuration.user_sftp_auth).title(),
            }

        output_objects.append({'object_type': 'html_form', 'text': html})

    if 'webdavs' in topics:

        # load current davs

        current_davs_dict = load_davs(client_id, configuration)
        if not current_davs_dict:
            
            # no current davs found
            
            current_davs_dict = {}

        default_authkeys = current_davs_dict.get('authkeys', '')
        default_authpassword = current_davs_dict.get('authpassword', '')
        username = client_alias(client_id)
        if configuration.user_davs_alias:
            username = extract_field(client_id, configuration.user_davs_alias)
            create_alias_link(username, client_id, configuration.user_home)
        davs_server = configuration.user_davs_show_address
        davs_port = configuration.user_davs_show_port
        html = \
        '''
<div id="davsaccess">
<form method="post" action="settingsaction.py">
<table class="davssettings fixedlayout">
<tr class="title"><td class="centertext">
WebDAVS access to your %(site)s account
</td></tr>
<tr><td>

</td></tr>
<tr><td>
You can configure WebDAVS login to your %(site)s account for transparent file
access from your PC or workstation.<br/>
<h3>Login Details</h3>
<ul>
<li>Host <em>%(davs_server)s</em></li>
<li>Port <em>%(davs_port)s</em></li>
<li>Username <em>%(username)s</em></li>
<li>%(auth_methods)s <em>as you choose below</em></li>
</ul>
</td></tr>
<tr><td>
<input type="hidden" name="topic" value="webdavs" />
<div class="div-webdavs-client-notes hidden">
<a href="javascript:toggleHidden('.div-webdavs-client-notes');"
    class="removeitemlink" title="Toggle view">
    Show less WebDAVS client details...</a>
<h3>Graphical WebDAVS access</h3>
Several native file browsers and web browsers are known to generally work for
graphical access to your %(site)s home over WebDAVS.
<br />
Enter the address https://%(davs_server)s:%(davs_port)s and when fill in the
login details:
<pre>
Username %(username)s
Password YOUR_PASSWORD_HERE
</pre>
other graphical clients should work as well.
<h3>Command line WebDAVS access on Linux/UN*X</h3>
Save something like the following lines in your local ~/.netrc
to avoid typing the full login details every time:<br />
<pre>
machine %(davs_server)s
login %(username)s
password YOUR_PASSWORD_HERE
</pre>
From then on you can use e.g. cadaver or fusedav to access your %(site)s home:
<pre>
cadaver https://%(davs_server)s:%(davs_port)s
</pre>
<pre>
fusedav https://%(davs_server)s:%(davs_port)s mig-home -o uid=$(id -u) -o gid=$(id -g)
</pre>
</div>
<div class="div-webdavs-client-notes">
<a href="javascript:toggleHidden('.div-webdavs-client-notes');"
    class="additemlink" title="Toggle view">
    Show more WebDAVS client details...</a>
</div>
'''
        
        keyword_keys = "authkeys"
        if 'publickey' in configuration.user_davs_auth:
            html += '''
</td></tr>
<tr><td>
<h3>Authorized Public Keys</h3>
You can use any existing RSA key, including the key.pem you received along with
your user certificate, or create a new one. In any case you need to save the
contents of the corresponding public key (X.pub) in the text area below, to be
able to connect with username and key as described in the Login Details.
<br/>'''
            area = '''
<textarea id="%(keyword_keys)s" cols=82 rows=5 name="publickeys">
%(default_authkeys)s
</textarea>
'''
            html += wrap_edit_area(keyword_keys, area, davs_edit, 'BASIC')
            html += '''
(leave empty to disable davs access with public keys)
</td></tr>
'''
            
        keyword_password = "******"
        if 'password' in configuration.user_davs_auth:
            # We only want a single password and a masked input field
            html += '''
<tr><td>
<h3>Authorized Password</h3>
Please enter and save your desired password in the text field below, to be able
to connect with username and password as described in the Login Details.
<br/>
<input type=password id="%(keyword_password)s" size=40 name="password"
value="%(default_authpassword)s" />
(leave empty to disable davs access with password)
</td></tr>
'''
        
        html += '''
<tr><td>
<input type="submit" value="Save WebDAVS Settings" />
</td></tr>
'''
        
        html += '''
</table>
</form>
</div>
'''
        html = html % {
            'default_authkeys': default_authkeys,
            'default_authpassword': default_authpassword,
            'site': configuration.short_title,
            'keyword_keys': keyword_keys,
            'keyword_password': keyword_password,
            'username': username,
            'davs_server': davs_server,
            'davs_port': davs_port,
            'auth_methods': ' / '.join(configuration.user_davs_auth).title(),
            }

        output_objects.append({'object_type': 'html_form', 'text': html})

    if 'ftps' in topics:

        # load current ftps

        current_ftps_dict = load_ftps(client_id, configuration)
        if not current_ftps_dict:
            
            # no current ftps found
            
            current_ftps_dict = {}

        default_authkeys = current_ftps_dict.get('authkeys', '')
        default_authpassword = current_ftps_dict.get('authpassword', '')
        username = client_alias(client_id)
        if configuration.user_ftps_alias:
            username = extract_field(client_id, configuration.user_ftps_alias)
            create_alias_link(username, client_id, configuration.user_home)
        ftps_server = configuration.user_ftps_show_address
        ftps_ctrl_port = configuration.user_ftps_show_ctrl_port
        html = \
        '''
<div id="ftpsaccess">
<form method="post" action="settingsaction.py">
<table class="ftpssettings fixedlayout">
<tr class="title"><td class="centertext">
FTPS access to your %(site)s account
</td></tr>
<tr><td>
</td></tr>
<tr><td>
You can configure FTPS login to your %(site)s account for efficient file
access.<br/>
<h3>Login Details</h3>
<ul>
<li>Host <em>%(ftps_server)s</em></li>
<li>Port <em>%(ftps_ctrl_port)s</em></li>
<li>Username <em>%(username)s</em></li>
<li>%(auth_methods)s <em>as you choose below</em></li>
</ul>
</td></tr>
<tr><td>
<input type="hidden" name="topic" value="ftps" />
<div class="div-ftps-client-notes hidden">
<a href="javascript:toggleHidden('.div-ftps-client-notes');"
    class="removeitemlink" title="Toggle view">
    Show less FTPS client details...</a>
<h3>Graphical FTPS access</h3>
The FireFTP plugin for Firefox is known to generally work for graphical
access to your %(site)s home over FTPS.
Enter the following values in the FireFTP Account Manager:
<pre>
Host %(ftps_server)s
Login %(username)s
Password YOUR_PASSWORD_HERE
Security FTPS
Port %(ftps_ctrl_port)s
</pre>
Other FTP clients and web browsers may work as well if you enter the address
ftps://%(ftps_server)s:%(ftps_ctrl_port)s
and fill in the login details when prompted:
<pre>
Username %(username)s
Password YOUR_PASSWORD_HERE
</pre>
<h3>Command line FTPS access on Linux/UN*X</h3>
Save something like the following lines in your local ~/.netrc
to avoid typing the full login details every time:<br />
<pre>
machine %(ftps_server)s
login %(username)s
password YOUR_PASSWORD_HERE
</pre>
From then on you can use e.g. lftp or CurlFtpFS to access your %(site)s home:
<!--
TODO: we need to provide the intermediate cert for server cert check like this
set ssl:ca-file sub.class1.server.ca.pem
-->
<pre>
lftp -e "set ssl:verify-certificate no; set ftp:ssl-protect-data on" \\
     -p %(ftps_ctrl_port)s %(ftps_server)s
</pre>
<pre>
curlftpfs -o ssl %(ftps_server)s:%(ftps_ctrl_port)s mig-home \\
          -o user=%(username)s -ouid=$(id -u) -o gid=$(id -g) -o no_verify_peer
</pre>
</div>
<div class="div-ftps-client-notes">
<a href="javascript:toggleHidden('.div-ftps-client-notes');"
    class="additemlink" title="Toggle view">Show more FTPS client details...
</a>
</div>
'''
        
        keyword_keys = "authkeys"
        if 'publickey' in configuration.user_ftps_auth:
            html += '''
</td></tr>
<tr><td>
<h3>Authorized Public Keys</h3>
You can use any existing RSA key, including the key.pem you received along with
your user certificate, or create a new one. In any case you need to save the
contents of the corresponding public key (X.pub) in the text area below, to be
able to connect with username and key as described in the Login Details.
<br/>
'''
            area = '''
<textarea id="%(keyword_keys)s" cols=82 rows=5 name="publickeys">
%(default_authkeys)s
</textarea>
'''
            html += wrap_edit_area(keyword_keys, area, ftps_edit, 'BASIC')
            html += '''
(leave empty to disable ftps access with public keys)
</td></tr>
'''
            
        keyword_password = "******"
        if 'password' in configuration.user_ftps_auth:

            # We only want a single password and a masked input field
            html += '''
<tr><td>
<h3>Authorized Password</h3>
Please enter and save your desired password in the text field below, to be able
to connect with username and password as described in the Login Details.
<br/>
<input type=password id="%(keyword_password)s" size=40 name="password"
value="%(default_authpassword)s" />
(leave empty to disable ftps access with password)
</td></tr>
'''
        
        html += '''
<tr><td>
<input type="submit" value="Save FTPS Settings" />
</td></tr>
'''
        
        html += '''
</table>
</form>
</div>
'''
        html = html % {
            'default_authkeys': default_authkeys,
            'default_authpassword': default_authpassword,
            'site': configuration.short_title,
            'keyword_keys': keyword_keys,
            'keyword_password': keyword_password,
            'username': username,
            'ftps_server': ftps_server,
            'ftps_ctrl_port': ftps_ctrl_port,
            'auth_methods': ' / '.join(configuration.user_ftps_auth).title(),
            }

        output_objects.append({'object_type': 'html_form', 'text': html})

    # if ARC-enabled server:
    if 'arc' in topics:
        # provide information about the available proxy, offer upload
        try:
            home_dir = os.path.normpath(base_dir)
            session_Ui = arc.Ui(home_dir, require_user_proxy=True)
            proxy = session_Ui.getProxy()
            if proxy.IsExpired():
                # can rarely happen, constructor will throw exception
                output_objects.append({'object_type': 'text', 
                                       'text': 'Proxy certificate is expired.'})
            else:
                output_objects.append({'object_type': 'text', 
                                       'text': 'Proxy for %s' \
                                       % proxy.GetIdentitySN()})
                output_objects.append(
                    {'object_type': 'text', 
                     'text': 'Proxy certificate will expire on %s (in %s sec.)'
                     % (proxy.Expires(), proxy.getTimeleft())
                     })
        except arc.NoProxyError, err:
            output_objects.append({'object_type':'warning',
                                   'text': 'No proxy certificate to load: %s' \
                                   % err.what()})
    
        output_objects = output_objects + arc.askProxy()
Пример #30
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)

    vgrid_name = accepted['vgrid_name'][-1]
    flags = ''.join(accepted['flags'])
    cert_id = accepted['cert_id'][-1]
    cert_dir = client_id_dir(cert_id)
    # inherited vgrid membership
    inherit_vgrid_member = False

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Remove %s' % configuration.site_vgrid_label
    output_objects.append({'object_type': 'header', 'text'
                          : 'Remove %s Owner' % \
                           configuration.site_vgrid_label})

    # Validity of user and vgrid names is checked in this init function so
    # no need to worry about illegal directory traversal through variables

    (ret_val, msg, _) = \
        init_vgrid_script_add_rem(vgrid_name, client_id, cert_id,
                                  'owner', configuration)
    if not ret_val:
        output_objects.append({'object_type': 'error_text', 'text'
                              : msg})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # don't remove if not already an owner

    if not vgrid_is_owner(vgrid_name, cert_id, configuration):
        output_objects.append({'object_type': 'error_text', 'text'
                              : '%s is not an owner of %s or a parent %s.'
                               % (cert_id, vgrid_name,
                                  configuration.site_vgrid_label)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # we need the local owners file to detect inherited ownerships

    (status, owners_direct) = vgrid_owners(vgrid_name, configuration, False)
    (all_status, owners) = vgrid_owners(vgrid_name, configuration, True)
    if not status or not all_status:
        logger.error('Error loading owners for %s: %s / %s'
                     % (vgrid_name, owners_direct, owners))
        output_objects.append({'object_type': 'error_text', 'text'
         : 'An internal error occurred, error conditions have been logged.'})
        output_objects.append({'object_type': 'text', 'text'
         : '''
         You can help us fix the problem by notifying the administrators
         via mail about what you wanted to do when the error happened.'''})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # find out whether to just remove an owner or delete the whole thing.
    # ask about delete if last or no direct owners.

    if len(owners_direct) > 1:
        
        logger.debug('Removing %s, one of several owners, from %s.' % 
                     (cert_id, vgrid_name))

        if not (cert_id in owners_direct):

            # the owner owns an upper vgrid, ownership is inherited
            # cannot remove, not last (inherited) owner

            logger.debug('Cannot delete: Inherited ownership.' + 
                         '\n Owners: %s,\n Direct owners: %s.' 
                         % (owners, owners_direct))
            output_objects.append({'object_type': 'error_text', 'text'
                                   : '''%s is owner of a parent %s. 
Owner removal has to be performed at the topmost vgrid''' % \
                                   (cert_id, configuration.site_vgrid_label)})
            return (output_objects, returnvalues.CLIENT_ERROR)

        else:

            # Remove any tracker admin rights
            
            if configuration.trac_admin_path:
                public_tracker_dir = \
                                   os.path.abspath(os.path.join(
                    configuration.vgrid_public_base, vgrid_name,
                    '.vgridtracker'))
                private_tracker_dir = \
                                    os.path.abspath(os.path.join(
                    configuration.vgrid_private_base, vgrid_name,
                    '.vgridtracker'))
                vgrid_tracker_dir = \
                                  os.path.abspath(os.path.join(
                    configuration.vgrid_files_home, vgrid_name,
                    '.vgridtracker'))
                for tracker_dir in [public_tracker_dir, private_tracker_dir,
                                    vgrid_tracker_dir]:
                    if not rm_tracker_admin(configuration, cert_id,
                                             vgrid_name, tracker_dir,
                                             output_objects):
                        return (output_objects, returnvalues.SYSTEM_ERROR)

            user_dir = os.path.abspath(os.path.join(configuration.user_home,
                                                    cert_dir)) + os.sep
        
            # Do not touch vgrid share if still a member of a parent vgrid
            
            if vgrid_is_member(vgrid_name, cert_id, configuration):
                # list is in top-down order 
                parent_vgrids = vgrid_list_parents(vgrid_name, configuration)
                inherit_vgrid_member = vgrid_name
                for parent in parent_vgrids:
                    if vgrid_is_member(parent, cert_id, configuration,
                                       recursive=False):
                        inherit_vgrid_member = parent
                        break
                output_objects.append(
                    {'object_type': 'text', 'text'
                     : '''NOTE: %s is still a member of parent %s %s.
                     Preserving access to corresponding %s.''' % \
                     (cert_id, configuration.site_vgrid_label,
                      inherit_vgrid_member, configuration.site_vgrid_label)
                     })
            else:
                (success, msg) = unlink_share(user_dir, vgrid_name)
                if not success: 
                    logger.error('Could not remove share link: %s.' % msg)
                    output_objects.append({'object_type': 'error_text', 'text'
                                           : 'Could not remove share links: %s.'
                                           % msg})
                    return (output_objects, returnvalues.SYSTEM_ERROR)

            # unlink shared web folders

            (success, msg) = unlink_web_folders(user_dir, vgrid_name)
            if not success: 
                logger.error('Could not remove web links: %s.' % msg)
                output_objects.append({'object_type': 'error_text', 'text'
                                       : 'Could not remove web links: %s.' 
                                       % msg})
                return (output_objects, returnvalues.SYSTEM_ERROR)

            # remove user from saved owners list
            (rm_status, rm_msg) = vgrid_remove_owners(configuration, vgrid_name,
                                                     [cert_id])
            if not rm_status:
                output_objects.append({'object_type': 'error_text', 'text'
                                       : '%s of owners of %s' 
                                       % (rm_msg, vgrid_name)})
                return (output_objects, returnvalues.SYSTEM_ERROR)

            # Any parent vgrid membership is left untouched here as we only
            # force a normal refresh in unmap_inheritance
            unmap_inheritance(configuration, vgrid_name, cert_id)

            output_objects.append({'object_type': 'text', 'text'
                          : '%s successfully removed as owner of %s!'
                           % (cert_id, vgrid_name)})
            output_objects.append({'object_type': 'link', 'destination':
                           'adminvgrid.py?vgrid_name=%s' % vgrid_name, 'text':
                           'Back to administration for %s' % vgrid_name})
            return (output_objects, returnvalues.OK)

    else:
        
        # no more direct owners - we try to remove this VGrid

        logger.debug('Leave %s from %s with no more direct owners: delete' %
                     (vgrid_name, cert_id))

        if not force(flags):
            output_objects.append({'object_type': 'text', 'text' : '''
No more direct owners of %s - leaving will result in the %s getting
deleted. Please use either of the links below to confirm or cancel.
''' % (vgrid_name, configuration.site_vgrid_label)})
            js_name = 'rmvgridowner%s' % hexlify(vgrid_name)
            helper = html_post_helper(js_name, 'rmvgridowner.py',
                                      {'vgrid_name': vgrid_name,
                                       'cert_id': cert_id, 'flags': 'f'})
            output_objects.append({'object_type': 'html_form', 'text': helper})
            output_objects.append({'object_type': 'link', 'destination':
                                   "javascript: %s();" % js_name, 'class':
                                   'removelink', 'text':
                                   'Really leave and delete %s' % vgrid_name})
            output_objects.append({'object_type': 'text', 'text' : ''})
            output_objects.append({'object_type': 'link', 'destination':
                                   'adminvgrid.py?vgrid_name=%s' % vgrid_name,
                                   'text': 'Back to administration for %s'
                                   % vgrid_name})
            return (output_objects, returnvalues.OK)

        # check if any resources participate or sub-vgrids depend on this one

        (status, subs) = vgrid_list_subvgrids(vgrid_name, configuration)

        if not status:
            logger.error('Error loading sub-%ss for %s: %s)'
                         % (configuration.site_vgrid_label, vgrid_name, subs))
            output_objects.append({'object_type': 'error_text', 'text' : '''
An internal error occurred, error conditions have been logged.'''})
            output_objects.append({'object_type': 'text', 'text' : '''
You can help us fix the problem by notifying the administrators
via mail about what you wanted to do when the error happened.'''})
            return (output_objects, returnvalues.CLIENT_ERROR)

        if len(subs) > 0:

            logger.debug('Cannot delete: still has sub-%ss %s.'
                         % (configuration.site_vgrid_label, subs))
            output_objects.append({'object_type': 'error_text', 'text' : \
    '%s has sub-structures and cannot be deleted.' % vgrid_name})
            output_objects.append({'object_type': 'text', 'text' : '''
To leave (and delete) %s, first remove its sub-structures: %s.'''
                                      % (vgrid_name, ', '.join(subs))})

            return (output_objects, returnvalues.CLIENT_ERROR)

        # we consider the local members and resources here, not inherited ones
        
        (member_status, members_direct) = vgrid_members(vgrid_name,
                                                        configuration,
                                                        False)
        (resource_status, resources_direct) = vgrid_resources(vgrid_name,
                                                              configuration,
                                                              False)
        if not member_status or not resource_status:
            logger.warning('failed to load %s members or resources: %s %s'
                           % (vgrid_name, members_direct, resources_direct))
            output_objects.append({'object_type': 'error_text', 'text' : \
    'could not load %s members or resources for %s.' % \
                                   (configuration.site_vgrid_label,
                                    vgrid_name)})
            return (output_objects, returnvalues.SYSTEM_ERROR)
        if len(resources_direct) > 0:
            logger.debug('Cannot delete: still has direct resources %s.'
                         % resources_direct)
            output_objects.append({'object_type': 'error_text', 'text' : \
    '%s still has resources and cannot be deleted.' % vgrid_name})
            output_objects.append({'object_type': 'text', 'text' : '''
To leave (and delete) %s, first remove the participating resources.'''
                                      % vgrid_name})

            return (output_objects, returnvalues.CLIENT_ERROR)

        if len(members_direct) > 0:

            logger.debug('Cannot delete: still has direct members %s.'
                         % members_direct)
            output_objects.append({'object_type': 'error_text', 'text' : \
    '%s still has members and cannot be deleted.' % vgrid_name})
            output_objects.append({'object_type': 'text', 'text' : '''
To leave (and delete) %s, first remove all members.'''
                                      % vgrid_name})

            return (output_objects, returnvalues.CLIENT_ERROR)

        # When reaching here, OK to remove the VGrid.
        #   if top-level: unlink, remove all files and directories, 
        #   in all cases: remove configuration entry for the VGrid

        if (cert_id in owners_direct):

            # owner owns this vgrid, direct ownership

            logger.debug('%s looks like a top-level %s.' % \
                         (configuration.site_vgrid_label, vgrid_name))
            logger.debug('Deleting all related files.')

            user_dir = os.path.abspath(os.path.join(configuration.user_home,
                                                    cert_dir)) + os.sep
            (share_lnk, msg1)  = unlink_share(user_dir, vgrid_name)
            (web_lnk, msg1)  = unlink_web_folders(user_dir, vgrid_name)
            (abandoned, msg2) = abandon_vgrid_files(vgrid_name, configuration)
        else:

            # owner owns an upper vgrid, ownership is inherited

            logger.debug('%s looks like a sub-%s, ownership inherited.'
                         % (vgrid_name, configuration.site_vgrid_label))
            logger.debug('Only removing entry, leaving files in place.')
            share_lnk = True
            web_lnk = True
            abandoned = True
            msg1 = ''
            msg2 = ''

        (removed, msg3) = remove_vgrid_entry(vgrid_name, configuration)

        output_objects.append({'object_type': 'text', 'text'
                                   : '%s has been removed with last owner.'
                                      % vgrid_name})

        output_objects.append({'object_type': 'link', 
                               'destination': 'vgridadmin.py', 
                               'text': 'Back to the overview.'})

        if not share_lnk or not web_lnk or not abandoned or not removed:

            logger.error('Errors while removing %s:\n%s.'
                         % (vgrid_name, '\n'.join([msg1,msg2,msg3])))

            output_objects.append({'object_type': 'error_text', 'text' : '''
An internal error occurred, error conditions have been logged.'''})
            output_objects.append({'object_type': 'text', 'text' : '''
You can help us fix the problem by notifying the administrators
via mail about what you wanted to do when the error happened.'''})
            return (output_objects, returnvalues.CLIENT_ERROR)

        else:

            # Remove vgrid from vgrid cache (after deleting all)
            unmap_vgrid(configuration, vgrid_name)
            return (output_objects, returnvalues.OK)
Пример #31
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)
Пример #32
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)
    client_dir = client_id_dir(client_id)
    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)

    job_ids = accepted['job_id']
    action = accepted['action'][-1]
    src = accepted['src']
    dst = accepted['dst'][-1]

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s live I/O' % configuration.short_title
    output_objects.append({'object_type': 'header', 'text'
                           : 'Request live communication with jobs'})

    if not action in valid_actions:
        output_objects.append({'object_type': 'error_text', 'text'
                               : 'Invalid action "%s" (supported: %s)' % \
                               (action, ', '.join(valid_actions))})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if action in post_actions and 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)

    if not job_ids or action in interactive_actions:
        job_id = ''
        if job_ids:
            job_id = job_ids[-1]
        output_objects.append({'object_type': 'text', 'text'
                          : '''
Fill in the live I/O details below to request communication with a running
job.
Job ID can be a full ID or a wild card pattern using "*" and "?" to match one
or more of your job IDs.
Use send output without source and destination paths to request upload of the
default stdio files from the job on the resource to the associated job_output
directory in your MiG home.
Destination is a always handled as a directory path to put source files into.
Source and destination paths are always taken relative to the job execution
directory on the resource and your MiG home respectively.
'''})
        html = '''
<table class="liveio">
<tr>
<td>
<form method="post" action="liveio.py">
<table class="liveio">
<tr><td class=centertext>
</td></tr>
<tr><td>
Action:<br />
<input type=radio name=action checked value="send" />send output
<input type=radio name=action value="get" />get input
</td></tr>
<tr><td>
Job ID:<br />
<input type=text size=60 name=job_id value="%s" />
</td></tr>
<tr><td>
Source path(s):<br />
<div id="srcfields">
<input type=text size=60 name=src value="" /><br />
</div>
</td></tr>
<tr><td>
Destination path:<br />
<input type=text size=60 name=dst value="" />
</td></tr>
<tr><td>
<input type="submit" value="Send request" />
</td></tr>
</table>
</form>
</td>
<td>
<script type="text/javascript">
fields = 1;
max_fields = 64;
function addInput() {
    if (fields < max_fields) {
        document.getElementById("srcfields").innerHTML += "<input type=text size=60 name=src value='' /><br />";
        fields += 1;
    } else {
        alert("Maximum " + max_fields + " source fields allowed!");
        document.form.add.disabled=true;
    }
}
</script>
<form name="addsrcform">
<input type="button" onclick="addInput(); return false;" name="add" value="Add another source field" />
</form>
</td>
</tr>
</table>
''' % job_id
        output_objects.append({'object_type': 'html_form', 'text'
                              : html})
        output_objects.append({'object_type': 'text', 'text': '''
Further live job control is avalable through your personal message queues.
They provide a basic interface for centrally storing messages under your grid
account and can be used to pass messages between jobs or for orchestrating
jobs before and during execution.
'''
                               })
        output_objects.append({'object_type': 'link', 'destination':
                               'mqueue.py',
                               'text': 'Message queue interface'})
        return (output_objects, returnvalues.OK)
    elif action in ['get', 'receive', 'input']:
        action = 'get'
        action_desc = 'will be downloaded to the job on the resource'
    elif action in ['put', 'send', 'output']:
        action = 'send'
        action_desc = 'will be uploaded from the job on the resource'
    else:
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'Invalid live io action: %s' % action})
        return (output_objects, returnvalues.CLIENT_ERROR)

    output_objects.append({'object_type': 'text', 'text'
                          : 'Requesting live I/O for %s'
                           % ', '.join(job_ids)})

    if action == 'get' and (not src or not dst):
        output_objects.append(
            {'object_type': 'error_text',
             'text': 'src and dst parameters required for live input'})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Automatic fall back to stdio files if output with no path provided
                
    if src:
        src_text = 'The files ' + ' '.join(src)
    else:
        src_text = 'The job stdio files'

    if dst:
        dst_text = 'the ' + dst + ' directory'
    else:
        dst_text = 'the corresponding job_output directory'

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

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

    filelist = []
    for job_id in job_ids:
        job_id = job_id.strip()

        # is job currently being executed?

        # Backward compatibility - all_jobs keyword should match all jobs

        if job_id == all_jobs:
            job_id = '*'

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

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

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

                logger.warning("%s tried to %s restricted path %s ! (%s)" % \
                                (client_id, op_name, real_path, job_id))

                continue

            # Insert valid job files in filelist for later treatment

            match.append(real_path)

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

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

    for filepath in filelist:

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

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

            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : ('You can only list status of your own jobs. '
                    'Please verify that you submitted the mRSL file '
                    'with job id "%s" (Could not unpickle mRSL file %s)'
                    ) % (job_id, filepath)})
            continue

        if job_dict['STATUS'] != 'EXECUTING':
            output_objects.append(
                {'object_type': 'text', 'text'
                 : 'Job %s is not currently being executed! Job status: %s'
                 % (job_id, job_dict['STATUS'])})
            continue

        if job_dict['UNIQUE_RESOURCE_NAME'] == 'ARC':
            output_objects.append(
                {'object_type': 'text', 'text'
                 : 'Job %s is submitted to ARC, details are not available!'
                 % job_id })
            continue

        last_live_update_dict = {}
        last_live_update_file = configuration.mig_system_files + os.sep\
             + job_id + '.last_live_update'
        if os.path.isfile(last_live_update_file):
            last_live_update_dict_unpickled = \
                unpickle(last_live_update_file, logger)
            if not last_live_update_dict_unpickled:
                output_objects.append({'object_type': 'error_text',
                        'text'
                        : 'Could not unpickle %s - skipping request!'
                         % last_live_update_file})
                continue

            if not last_live_update_dict_unpickled.has_key(
                'LAST_LIVE_UPDATE_REQUEST_TIMESTAMP'):
                output_objects.append(
                    {'object_type': 'error_text',
                     'text': 'Could not find needed key in %s.'
                     % last_live_update_file})
                continue

            last_live_update_request = \
                last_live_update_dict_unpickled['LAST_LIVE_UPDATE_REQUEST_TIMESTAMP'
                    ]

            difference = datetime.datetime.now()- last_live_update_request
            try:
                min_delay = \
                    int(configuration.min_seconds_between_live_update_requests)
            except:
                min_delay = 30

            if difference.seconds < min_delay:
                output_objects.append(
                    {'object_type': 'error_text',
                     'text': ('Request not allowed, you must wait at least ' \
                              '%s seconds between live update requests!'
                              ) % min_delay})
                continue

        # save this request to file to avoid DoS from a client request loop.

        last_live_update_dict['LAST_LIVE_UPDATE_REQUEST_TIMESTAMP'] = \
            datetime.datetime.now()
        pickle_ret = pickle(last_live_update_dict,
                            last_live_update_file, logger)
        if not pickle_ret:
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : 'Error saving live io request timestamp to last_live_update '
                 'file, request not sent!'})
            continue

        # #
        # ## job is being executed right now, send live io request to frontend
        # #

        # get resource_config, needed by scp_file_to_resource
        #(status, resource_config) = get_resource_configuration(
        #    resource_home, unique_resource_name, logger)

        resource_config = job_dict['RESOURCE_CONFIG']
        (status, exe) = get_resource_exe(resource_config, job_dict['EXE'],
                                         logger)
        if not status:
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : 'Could not get exe configuration for job %s' % job_id})
            continue

        local_file = '%s.%supdate' % (job_dict['LOCALJOBNAME'], action)
        if not os.path.exists(local_file):

            # create

            try:
                filehandle = open(local_file, 'w')
                filehandle.write('job_id '
                                  + job_dict['JOB_ID'] + '\n')
                filehandle.write('localjobname '
                                  + job_dict['LOCALJOBNAME'] + '\n')
                filehandle.write('execution_user '
                                  + exe['execution_user'] + '\n')
                filehandle.write('execution_node '
                                  + exe['execution_node'] + '\n')
                filehandle.write('execution_dir ' + exe['execution_dir']
                                  + '\n')
                filehandle.write('target liveio\n')

                # Leave defaults src and dst to FE script if not provided
                
                if src:
                    filehandle.write('source ' + ' '.join(src) + '\n')
                if dst:
                    filehandle.write('destination ' + dst + '\n')

                # Backward compatible test for shared_fs - fall back to scp

                if exe.has_key('shared_fs') and exe['shared_fs']:
                    filehandle.write('copy_command cp\n')
                    filehandle.write('copy_frontend_prefix \n')
                    filehandle.write('copy_execution_prefix \n')
                else:
                    filehandle.write('copy_command scp -B\n')
                    filehandle.write('copy_frontend_prefix ${frontend_user}@${frontend_node}:\n'
                            )
                    filehandle.write('copy_execution_prefix ${execution_user}@${execution_node}:\n'
                            )

                filehandle.write('### END OF SCRIPT ###\n')
                filehandle.close()
            except Exception, exc:
                pass

        if not os.path.exists(local_file):
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : '.%supdate file not available on %s server' % \
                 (action, configuration.short_title)})
            continue

        scpstatus = copy_file_to_resource(local_file, '%s.%supdate'
                 % (job_dict['LOCALJOBNAME'], action), resource_config, logger)
        if not scpstatus:
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : 'Error sending request for live io to resource!'})
            continue
        else:
            output_objects.append(
                {'object_type': 'text', 'text'
                 : 'Request for live io was successfully sent to the resource!'
                 })
            output_objects.append(
                {'object_type': 'text', 'text'
                 : '%s %s and should become available in %s in a minute.' % \
                 (src_text, action_desc, dst_text)
                 })
            if action == 'send':
                if not dst:
                    target_path = '%s/%s/*' % (job_output_dir, job_id)
                else:
                    target_path = dst
                output_objects.append({'object_type': 'link', 'destination'
                                       : 'ls.py?path=%s' % target_path,
                                       'text': 'View uploaded files'})
            else:
                output_objects.append({'object_type': 'link', 'destination'
                                       : 'ls.py?path=%s' % ';path='.join(src),
                                       'text': 'View files for download'})

        try:
            os.remove(local_file)
        except Exception, exc:
            pass
Пример #33
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'] = 'Delete frozen archive'
    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)

    flavor = accepted['flavor'][-1]

    if not flavor in freeze_flavors.keys():
        output_objects.append({'object_type': 'error_text', 'text':
                           'Invalid freeze flavor: %s' % flavor})
        return (output_objects, returnvalues.CLIENT_ERROR)

    title = freeze_flavors[flavor]['deletefreeze_title']
    output_objects.append({'object_type': 'header', 'text': title})
    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = title

    if not configuration.site_enable_freeze:
        output_objects.append({'object_type': 'text', 'text':
                               '''Freezing archives is disabled on this site.
Please contact the Grid admins %s if you think it should be enabled.
''' % configuration.admin_email})
        return (output_objects, returnvalues.OK)

    freeze_id = accepted['freeze_id'][-1]

    # NB: the restrictions on freeze_id prevents illegal directory traversal

    if not is_frozen_archive(freeze_id, configuration):
        logger.error("%s: invalid freeze '%s': %s" % (op_name,
                                                      client_id, freeze_id))
        output_objects.append({'object_type': 'error_text',
                               'text': "No such frozen archive: '%s'"
                               % freeze_id})
        return (output_objects, returnvalues.CLIENT_ERROR)
    
    (load_status, freeze_dict) = get_frozen_archive(freeze_id, configuration)
    if not load_status:
        logger.error("%s: load failed for '%s': %s" % \
                     (op_name, freeze_id, freeze_dict))
        output_objects.append(
            {'object_type': 'error_text',
             'text': 'Could not read frozen archive details for %s'
             % freeze_id})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # Prevent easy delete if the frozen archive if configuration forbids it
    if configuration.site_permanent_freeze:
        output_objects.append(
            {'object_type': 'error_text', 'text':
             "Can't delete frozen archive '%s' yourself due to site policy"
             % freeze_id})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Make sure the frozen archive belongs to the user trying to delete it
    if client_id != freeze_dict['CREATOR']:
        logger.error("%s: illegal access attempt for '%s': %s" % \
                         (op_name, freeze_id, client_id))
        output_objects.append({'object_type': 'error_text', 'text': \
        'You are not the owner of frozen archive "%s"' % freeze_id})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if freeze_dict.get('FLAVOR','freeze') != flavor:
        logger.error("%s: flavor mismatch for '%s': %s vs %s" % \
                     (op_name, freeze_id, flavor, freeze_dict))
        output_objects.append({'object_type': 'error_text', 'text'
                               : 'No such %s archive "%s"' % (flavor,
                                                              freeze_id)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Delete the frozen archive
    (status, msg) = delete_frozen_archive(freeze_id, configuration)
    
    # If something goes wrong when trying to delete frozen archive
    # freeze_id, an error is displayed.
    if not status:
        logger.error("%s: failed for '%s': %s" % (op_name,
                                                  freeze_id, msg))
        output_objects.append({'object_type': 'error_text', 'text'
                               : 'Could not remove %s frozen archive: %s'
                               % (freeze_id, msg)})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # If deletion of frozen archive freeze_id is successful, we just
    # return OK
    else:
        logger.info("%s: successful for '%s': %s" % (op_name,
                                                      freeze_id, client_id))
        output_objects.append(
            {'object_type': 'text', 'text'
             : 'Successfully deleted frozen archive: "%s"' % freeze_id})
        output_objects.append({'object_type': 'link', 'destination':
                               'freezedb.py',
                               'class': 'infolink',
                               'title': 'Show frozen archives',
                               'text': 'Show frozen archives'})
        return (output_objects, returnvalues.OK) 
Пример #34
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)

    meta = (
        """<meta http-equiv="refresh" content="%s" />
"""
        % configuration.sleep_secs
    )
    style = themed_styles(configuration)
    script = """
<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" >

$(document).ready(function() {

          // table initially sorted by col. 1 (name)
          var sortOrder = [[1,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;
          }
          $("table.monitor").tablesorter({widgets: ["zebra"],
                                          textExtraction: imgTitle,
                                         });
          $("table.monitor").each(function () {
              try {
                  $(this).trigger("sorton", [sortOrder]);
              } catch(err) {
                  /* tablesorter chokes on empty tables - just continue */
              }
          });
     }
);
</script>
"""

    title_entry = find_entry(output_objects, "title")
    title_entry["text"] = "%s Monitor" % configuration.short_title
    title_entry["meta"] = meta
    title_entry["style"] = style
    title_entry["javascript"] = script

    allowed_vgrids = user_allowed_vgrids(configuration, client_id)
    vgrid_list = accepted["vgrid_name"]
    if all_vgrids in accepted["vgrid_name"]:
        vgrid_list = [i for i in vgrid_list if all_vgrids != i] + allowed_vgrids

    # Force list to sequence of unique entries

    for vgrid_name in set(vgrid_list):
        html = ""
        if not vgrid_is_owner_or_member(vgrid_name, client_id, configuration):
            output_objects.append(
                {
                    "object_type": "error_text",
                    "text": """You must be an owner or member of %s %s
to access the monitor."""
                    % (vgrid_name, configuration.site_vgrid_label),
                }
            )
            return (output_objects, returnvalues.CLIENT_ERROR)

        monitor_file = os.path.join(configuration.vgrid_home, vgrid_name, "%s.html" % configuration.vgrid_monitor)
        try:
            monitor_fd = open(monitor_file, "r")
            past_header = False
            for line in monitor_fd:
                if -1 != line.find("end of raw header"):
                    past_header = True
                    continue
                if not past_header:
                    continue
                if -1 != line.find("begin raw footer:"):
                    break
                html += str(line)
            monitor_fd.close()
        except Exception, exc:
            output_objects.append(
                {
                    "object_type": "error_text",
                    "text": "Error reading %s monitor page (%s)" % (configuration.site_vgrid_label, exc),
                }
            )
            return (output_objects, returnvalues.SYSTEM_ERROR)

        output_objects.append({"object_type": "html_form", "text": html})
Пример #35
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, op_menu=False)
    client_dir = client_id_dir(client_id)
    defaults = signature()[1]
    (validate_status, accepted) = validate_input(user_arguments_dict,
            defaults, output_objects, allow_rejects=False)
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s certificate request' % configuration.short_title
    title_entry['skipmenu'] = True
    form_fields = ['full_name', 'organization', 'email', 'country', 'state',
                   'password', 'verifypassword', 'comment']
    title_entry['style'] = themed_styles(configuration)
    title_entry['javascript'] = cert_js_helpers(form_fields)
    output_objects.append({'object_type': 'html_form',
                           'text':'''
 <div id="contextual_help">
  <div class="help_gfx_bubble"><!-- graphically connect field with help text --></div>
  <div class="help_message"><!-- filled by js --></div>
 </div>
'''                       })
    header_entry = {'object_type': 'header', 'text'
                    : 'Welcome to the %s certificate request page' % \
                    configuration.short_title}
    output_objects.append(header_entry)
    
    # Please note that base_dir must end in slash to avoid access to other
    # user dirs when own name is a prefix of another user name

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

    user_fields = {'full_name': '', 'organization': '', 'email': '',
                   'state': '', 'country': '', 'password': '',
                   'verifypassword': ''}
    if not os.path.isdir(base_dir) and client_id:

        # Redirect to extcert page with certificate requirement but without
        # changing access method (CGI vs. WSGI).

        extcert_url = os.environ['REQUEST_URI'].replace('-sid', '-bin')
        extcert_url = os.path.join(os.path.dirname(extcert_url), 'extcert.py')
        extcert_link = {'object_type': 'link', 'destination': extcert_url,
                        'text': 'Sign up with existing certificate (%s)' % client_id}
        output_objects.append({'object_type': 'warning', 'text'
                              : 'Apparently you already have a suitable %s certificate that you may sign up with:' % \
                                configuration.short_title
                              })
        output_objects.append(extcert_link)
        output_objects.append({'object_type': 'warning', 'text'
                              : 'However, if you want a dedicated %s certificate you can still request one below:' % \
                                configuration.short_title
                              })
    elif client_id:
        for entry in (title_entry, header_entry):
            entry['text'] = entry['text'].replace('request', 'request / renew')
        output_objects.append({'object_type': 'html_form', 'text'
                              : '''<p>
Apparently you already have a valid %s certificate, but if it is about to
expire you can renew it by posting the form below. Renewal with changed fields
is <span class=mandatory>not</span> supported, so all fields including your
original password must remain unchanged for renew to work. Otherwise it
results in a request for a new account and certificate without access to your
old files, jobs and privileges.</p>''' % \
                               configuration.short_title})
        user_fields.update(distinguished_name_to_user(client_id))

    user_fields.update({
        'valid_name_chars': html_escape(valid_name_chars),
        'valid_password_chars': html_escape(valid_password_chars),
        'password_min_len': password_min_len,
        'password_max_len': password_max_len,
        'site': configuration.short_title
        })

    output_objects.append({'object_type': 'html_form', 'text'
                          : """
Please enter your information in at least the <span class=mandatory>mandatory</span> fields below and press the Send button to submit the certificate request to the %(site)s administrators.
<p class='criticaltext highlight_message'>
IMPORTANT: Please help us verify your identity by providing Organization and Email data that we can easily validate!<br />
That is, if You're a student/employee at KU, please enter institute acronym (NBI, DIKU, etc.) in the Organization field and use your corresponding [email protected] or USER@*.ku.dk address in the Email field.
</p>
<hr />
<div class=form_container>
<!-- use post here to avoid field contents in URL -->
<form method=post action=reqcertaction.py onSubmit='return validate_form();'>
<table>
<tr><td class='mandatory label'>Full name</td><td><input id='full_name_field' type=text name=cert_name value='%(full_name)s' /></td><td class=fill_space><br /></td></tr>
<tr><td class='mandatory label'>Email address</td><td><input id='email_field' type=text name=email value='%(email)s' /> </td><td class=fill_space><br /></td></tr>
<tr><td class='mandatory label'>Organization</td><td><input id='organization_field' type=text name=org value='%(organization)s' /></td><td class=fill_space><br /></td></tr>
<tr><td class='mandatory label'>Two letter country-code</td><td><input id='country_field' type=text name=country maxlength=2 value='%(country)s' /></td><td class=fill_space><br /></td></tr>
<tr><td class='optional label'>State</td><td><input id='state_field' type=text name=state value='%(state)s' /> </td><td class=fill_space><br /></td></tr>
<tr><td class='mandatory label'>Password</td><td><input id='password_field' type=password name=password maxlength=%(password_max_len)s value='%(password)s' /> </td><td class=fill_space><br /></td></tr>
<tr><td class='mandatory label'>Verify password</td><td><input id='verifypassword_field' type=password name=verifypassword maxlength=%(password_max_len)s value='%(verifypassword)s' /></td><td class=fill_space><br /></td></tr>
<tr><td class='optional label'>Optional comment or reason why you should<br />be granted a %(site)s certificate:</td><td><textarea id='comment_field' rows=4 name=comment></textarea></td><td class=fill_space><br /></td></tr>
<tr><td class='label'><!-- empty area --></td><td><input id='submit_button' type=submit value=Send /></td><td class=fill_space><br /></td></tr>
</table>
</form>
</div>
<hr />
<br />
<div class='warn_message'>Please note that passwords may be accessible to the %(site)s administrators!</div>
<br />
<!-- Hidden help text -->
<div id='help_text'>
  <div id='full_name_help'>Your full name, restricted to the characters in '%(valid_name_chars)s'</div>
  <div id='organization_help'>Organization name or acronym  matching email</div>
  <div id='email_help'>Email address associated with your organization if at all possible</div>
  <div id='country_help'>Country code of your organization and on the form DE/DK/GB/US/.. , <a href='http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.html'>help</a></div>
  <div id='state_help'>Optional state of your organization, please just leave empty unless it is in the US or similar</div>
  <div id='password_help'>Password is restricted to the characters in '%(valid_password_chars)s and must be %(password_min_len)s to %(password_max_len)s characters long'</div>
  <div id='verifypassword_help'>Please repeat password</div>
  <div id='comment_help'>Optional, but a short informative comment may help us verify your certificate needs and thus speed up our response.</div>
</div>
""" % user_fields})

    return (output_objects, returnvalues.OK)
Пример #36
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, op_menu=False)
    defaults = signature()[1]
    logger.debug('in extoidaction: %s' % user_arguments_dict)
    (validate_status, accepted) = validate_input(user_arguments_dict,
            defaults, output_objects, allow_rejects=False)
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    # Unfortunately OpenID does not use POST
    #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)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s OpenID account sign up' % configuration.short_title
    title_entry['skipmenu'] = True
    output_objects.append({'object_type': 'header', 'text'
                          : '%s OpenID account sign up' % \
                            configuration.short_title 
                           })

    admin_email = configuration.admin_email
    smtp_server = configuration.smtp_server
    user_pending = os.path.abspath(configuration.user_pending)

    # force name to capitalized form (henrik karlsen -> Henrik Karlsen)

    id_url = os.environ['REMOTE_USER'].strip()
    openid_prefix = configuration.user_ext_oid_provider.rstrip('/') + '/'
    raw_login = id_url.replace(openid_prefix, '')
    full_name = accepted['openid.sreg.full_name'][-1].strip().title()
    country = accepted['openid.sreg.country'][-1].strip().upper()
    state = accepted['state'][-1].strip().title()
    organization = accepted['openid.sreg.organization'][-1].strip()
    organizational_unit = accepted['openid.sreg.organizational_unit'][-1].strip()
    locality = accepted['openid.sreg.locality'][-1].strip()

    # lower case email address

    email = accepted['openid.sreg.email'][-1].strip().lower()
    password = accepted['password'][-1]
    #verifypassword = accepted['verifypassword'][-1]

    # keep comment to a single line

    comment = accepted['comment'][-1].replace('\n', '   ')

    # single quotes break command line format - remove

    comment = comment.replace("'", ' ')

    user_dict = {
        'full_name': full_name,
        'organization': organization,
        'organizational_unit': organizational_unit,
        'locality': locality,
        'state': state,
        'country': country,
        'email': email,
        'password': password,
        'comment': comment,
        'expire': int(time.time() + oid_valid_days * 24 * 60 * 60),
        'openid_names': [raw_login],
        'auth': ['extoid'],
        }
    fill_distinguished_name(user_dict)
    user_id = user_dict['distinguished_name']
    if configuration.user_openid_providers and configuration.user_openid_alias:
        user_dict['openid_names'].append(
            user_dict[configuration.user_openid_alias])

    req_path = None
    try:
        (os_fd, req_path) = tempfile.mkstemp(dir=user_pending)
        os.write(os_fd, dumps(user_dict))
        os.close(os_fd)
    except Exception, err:
        logger.error('Failed to write OpenID account request to %s: %s'
                      % (req_path, err))
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'Request could not be sent to grid administrators. Please contact them manually on %s if this error persists.'
                               % admin_email})
        return (output_objects, returnvalues.SYSTEM_ERROR)
Пример #37
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'] = 'Delete runtime environment'
    output_objects.append({'object_type': 'header', 'text'
                           : 'Delete runtime environment'})
    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)

    re_name = accepted['re_name'][-1]

    if not valid_dir_input(configuration.re_home, re_name):
        logger.warning(
            "possible illegal directory traversal attempt re_name '%s'"
            % re_name)
        output_objects.append({'object_type': 'error_text', 'text'
                               : 'Illegal runtime environment name: "%s"'
                               % re_name})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Check whether re_name represents a runtime environment
    if not is_runtime_environment(re_name, configuration):
        output_objects.append({'object_type': 'error_text',
                               'text': "No such runtime environment: '%s'"
                               % re_name})
        return (output_objects, returnvalues.CLIENT_ERROR)
    
    re_dict = get_re_dict(re_name, configuration)
    if not re_dict[0]:
        output_objects.append(
            {'object_type': 'error_text',
             'text': 'Could not read runtime environment details for %s'
             % re_name})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # Make sure the runtime environment belongs to the user trying to delete it
    if client_id != re_dict[0]['CREATOR']:
        output_objects.append({'object_type': 'error_text', 'text': \
        'You are not the owner of runtime environment "%s"' % re_name})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Prevent delete if the runtime environment is used by any resources
    actives = resources_using_re(configuration, re_name)

    # If the runtime environment is active, an error message is printed, along
    # with a list of the resources using the runtime environment
    if actives:
        output_objects.append(
            {'object_type': 'error_text', 'text':
             "Can't delete runtime environment '%s' in use by resources:"
             % re_name})
        output_objects.append({'object_type': 'list', 'list'
                               : actives})
        output_objects.append({'object_type': 'link', 'destination': 'redb.py',
                               'class': 'infolink', 'title':
                               'Show runtime environments',
                               'text': 'Show runtime environments'})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Delete the runtime environment
    (status, msg) = delete_runtimeenv(re_name, configuration)
    
    # If something goes wrong when trying to delete runtime environment
    # re_name, an error is displayed.
    if not status:
        output_objects.append({'object_type': 'error_text', 'text'
                               : 'Could not remove %s runtime environment: %s'
                               % (re_name, msg)})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # If deletion of runtime environment re_name is successful, we just
    # return OK
    else:
        output_objects.append(
            {'object_type': 'text', 'text'
             : 'Successfully deleted runtime environment: "%s"' % re_name})
        output_objects.append({'object_type': 'link', 'destination': 'redb.py',
                               'class': 'infolink',
                               'title': 'Show runtime environments',
                               'text': 'Show runtime environments'})
        return (output_objects, returnvalues.OK) 
Пример #38
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,
        require_user=False
        )
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s certificate sign up' % configuration.short_title
    title_entry['skipmenu'] = True
    form_fields = ['cert_id', 'cert_name', 'organization', 'email', 'country', 'state',
                   'comment']
    title_entry['style'] = themed_styles(configuration)
    title_entry['javascript'] = cert_js_helpers(form_fields)
    output_objects.append({'object_type': 'html_form',
                           'text':'''
 <div id="contextual_help">
  <div class="help_gfx_bubble"><!-- graphically connect field with help text--></div>
  <div class="help_message"><!-- filled by js --></div>
 </div>
'''                       })
    header_entry = {'object_type': 'header', 'text'
                    : 'Welcome to the %s certificate sign up page' % \
                    configuration.short_title}
    output_objects.append(header_entry)
    
    # Redirect to reqcert page without certificate requirement but without
    # changing access method (CGI vs. WSGI).
    
    certreq_url = os.environ['REQUEST_URI'].replace('-bin', '-sid')
    certreq_url = os.path.join(os.path.dirname(certreq_url), 'reqcert.py')
    certreq_link = {'object_type': 'link', 'destination': certreq_url,
                    'text': 'Request a new %s certificate' % \
                            configuration.short_title }
    new_user = distinguished_name_to_user(client_id)

    # If cert auto create is on, add user without admin interaction

    if configuration.auto_add_cert_user == False:
        extcertaction = 'extcertaction.py' 
    else:
        extcertaction = 'autocreate.py'

    output_objects.append({'object_type': 'html_form', 'text'
                          : """
This page is used to sign up for %(site)s with an existing certificate from a Certificate Authority (CA) allowed for %(site)s.
You can use it if you already have a x509 certificate from another accepted CA. In this way you can simply use your existing certificate for %(site)s access instead of requesting a new one.
<br />
The page tries to auto load any certificate your browser provides and fill in the fields accordingly, but in case it can't guess all <span class=mandatory>mandatory</span> fields, you still need to fill in those.<br />
Please enter any missing information below and press the Send button to submit the external certificate sign up request to the %(site)s administrators.
<p class='criticaltext highlight_message'>IMPORTANT: Please help us verify your identity by providing Organization and Email data that we can easily validate!<br />
That is, if You're a student/employee at KU, please enter institute acronym (NBI, DIKU, etc.) in the Organization field and use your corresponding [email protected] or USER@*.ku.dk address in the Email field.</p>
<hr />
<div class=form_container>
<!-- use post here to avoid field contents in URL -->
<form method=post action=%(extcertaction)s onSubmit='return validate_form();'>
<table>
<tr><td class='mandatory label'>Certificate DN</td><td><input id='cert_id_field' type=text size=%(dn_max_len)s maxlength=%(dn_max_len)s name=cert_id value='%(client_id)s' /></td><td class=fill_space></td></tr>
<tr><td class='mandatory label'>Full name</td><td><input id='cert_name_field' type=text name=cert_name value='%(common_name)s' /></td><td class=fill_space></td></tr>
<tr><td class='mandatory label'>Email address</td><td><input id='email_field' type=text name=email value='%(email)s' /></td><td class=fill_space></td></tr>
<tr><td class='mandatory label'>Organization</td><td><input id='organization_field' type=text name=org value='%(org)s' /></td><td class=fill_space></td></tr>
<tr><td class='mandatory label'>Two letter country-code</td><td><input id='country_field' type=text name=country maxlength=2 value='%(country)s' /></td><td class=fill_space></td></tr>
<tr><td class='optional label'>State</td><td><input id='state_field' type=text name=state value='%(state)s' /></td><td class=fill_space></td></tr>
<tr><td class='optional label'>Comment or reason why you should<br />be granted a %(site)s certificate:</td><td><textarea id='comment_field' rows=4 name=comment></textarea></td><td class=fill_space></td></tr>
<tr><td class='label'><!-- empty area --></td><td><input id='submit_button' type='submit' value='Send' /></td><td class=fill_space></td></tr>
</table>
</form>
</div>
<!-- Hidden help text -->
<div id='help_text'>
  <div id='cert_id_help'>Must be the exact Distinguished Name (DN) of your certificate</div>
  <div id='cert_name_help'>Your full name, restricted to the characters in '%(valid_name_chars)s'</div>
  <div id='organization_help'>Organization name or acronym  matching email</div>
  <div id='email_help'>Email address associated with your organization if at all possible</div>
  <div id='country_help'>Country code of your organization and on the form DE/DK/GB/US/.. , <a href='http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.html'>help</a></div>
  <div id='state_help'>Optional state of your organization, please just leave empty unless it is in the US or similar</div>
  <div id='comment_help'>Optional, but a short informative comment may help us verify your certificate needs and thus speed up our response.</div>
</div>
"""
                           % {
        'extcertaction': extcertaction,
        'valid_name_chars': valid_name_chars,
        'client_id': client_id,
        'dn_max_len': dn_max_len,
        'common_name': new_user.get('full_name', ''),
        'org': new_user.get('organization', ''),
        'email': new_user.get('email', ''),
        'state': new_user.get('state', ''),
        'country': new_user.get('country', ''),
        'site': configuration.short_title,
        }})

    return (output_objects, returnvalues.OK)
Пример #39
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, op_menu=False
    )
    defaults = signature()[1]
    logger.debug("in extoidaction: %s" % user_arguments_dict)
    (validate_status, accepted) = validate_input(user_arguments_dict, defaults, output_objects, allow_rejects=False)
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    # Unfortunately OpenID does not use POST
    # if not correct_handler('GET'):
    #    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 OpenID sign up" % configuration.short_title
    title_entry["skipmenu"] = True
    output_objects.append({"object_type": "header", "text": "%s OpenID sign up" % configuration.short_title})

    admin_email = configuration.admin_email
    smtp_server = configuration.smtp_server
    user_pending = os.path.abspath(configuration.user_pending)

    # force name to capitalized form (henrik karlsen -> Henrik Karlsen)

    id_url = os.environ["REMOTE_USER"].strip()
    openid_prefix = configuration.user_openid_providers[0].rstrip("/") + "/"
    raw_login = id_url.replace(openid_prefix, "")
    full_name = accepted["openid.sreg.full_name"][-1].strip().title()
    country = accepted["openid.sreg.country"][-1].strip().upper()
    state = accepted["state"][-1].strip().title()
    organization = accepted["openid.sreg.organization"][-1].strip()
    organizational_unit = accepted["openid.sreg.organizational_unit"][-1].strip()
    locality = accepted["openid.sreg.locality"][-1].strip()

    # lower case email address

    email = accepted["openid.sreg.email"][-1].strip().lower()
    password = accepted["password"][-1]
    # verifypassword = accepted['verifypassword'][-1]

    # keep comment to a single line

    comment = accepted["comment"][-1].replace("\n", "   ")

    # single quotes break command line format - remove

    comment = comment.replace("'", " ")

    user_dict = {
        "full_name": full_name,
        "organization": organization,
        "organizational_unit": organizational_unit,
        "locality": locality,
        "state": state,
        "country": country,
        "email": email,
        "password": password,
        "comment": comment,
        "expire": int(time.time() + oid_valid_days * 24 * 60 * 60),
        "openid_names": [raw_login],
    }
    fill_distinguished_name(user_dict)
    user_id = user_dict["distinguished_name"]
    if configuration.user_openid_providers and configuration.user_openid_alias:
        user_dict["openid_names"].append(user_dict[configuration.user_openid_alias])

    req_path = None
    try:
        (os_fd, req_path) = tempfile.mkstemp(dir=user_pending)
        os.write(os_fd, dumps(user_dict))
        os.close(os_fd)
    except Exception, err:
        logger.error("Failed to write certificate request to %s: %s" % (req_path, err))
        output_objects.append(
            {
                "object_type": "error_text",
                "text": "Request could not be sent to grid administrators. Please contact them manually on %s if this error persists."
                % admin_email,
            }
        )
        return (output_objects, returnvalues.SYSTEM_ERROR)
Пример #40
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)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Manage jobs'
    output_objects.append({'object_type': 'header', 'text'
                          : 'Manage Jobs'})
    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'View status of all submitted jobs'})
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<form method="post" action="jobstatus.py">
Sort by modification time: <input type="radio" name="flags" value="sv" />yes
<input type="radio" name="flags" checked="checked" value="vi" />no<br />
<input type="hidden" name="job_id" value="*" />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Show All" />
</form>
    """})
    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'View status of individual jobs'})
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
Filter job IDs (* and ? wildcards are supported)<br />
<form method="post" action="jobstatus.py">
Job ID: <input type="text" name="job_id" value="*" size="30" /><br />
Show only <input type="text" name="max_jobs" size="6" value=5 /> first matching jobs<br />
Sort by modification time: <input type="radio" name="flags" checked="checked" value="vsi" />yes
<input type="radio" name="flags" value="vi" />no<br />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Show" />
</form>
    """})
    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Resubmit job'})
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<form method="post" action="resubmit.py">
Job ID: <input type="text" name="job_id" size="30" /><br />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Submit" />
</form>
    """})
    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Freeze pending job'})
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<form method="post" action="jobaction.py">
Job ID: <input type="text" name="job_id" size="30" /><br />
<input type="hidden" name="action" value="freeze" />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Freeze job" />
</form>
    """})
    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Thaw frozen job'})
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<form method="post" action="jobaction.py">
Job ID: <input type="text" name="job_id" size="30" /><br />
<input type="hidden" name="action" value="thaw" />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Thaw job" />
</form>
    """})
    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Cancel pending or executing job'})
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<form method="post" action="jobaction.py">
Job ID: <input type="text" name="job_id" size="30" /><br />
<input type="hidden" name="action" value="cancel" />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Cancel job" />
</form>
    """})
    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Request live I/O'})
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<form method="post" action="liveio.py">
Job ID: <input type="text" name="job_id" size="30" /><br />
<input type="hidden" name="output_format" value="html" />
<input type="submit" value="Request" />
</form>
<br />
    """})
    return (output_objects, status)
Пример #41
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)
    client_dir = client_id_dir(client_id)

    valid_langs = {'sh': 'shell', 'python': 'python'}
    valid_flavors = {'user': '******',
                     'resource': 'vgridscriptgen'}
    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)

    flags = ''.join(accepted['flags'])
    langs = accepted['lang']
    flavor_list = accepted['flavor']
    sh_cmd = accepted['sh_cmd'][-1]
    python_cmd = accepted['python_cmd'][-1]

    flavors = []

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Script generator'
    output_objects.append({'object_type': 'header', 'text'
                          : 'Script generator'})

    status = returnvalues.OK

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

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

    if 'h' in flags:
        output_objects = usage(output_objects, valid_langs,
                               valid_flavors)
        return (output_objects, status)

    # Filter out any invalid flavors to avoid illegal filenames, etc.

    for f in flavor_list:
        if f in valid_flavors.keys():
            flavors.append(f)

    # Default to user scripts

    if not flavors:
        if flavor_list:
            output_objects.append({'object_type': 'text', 'text'
                                  : 'No valid flavors specified - falling back to user scripts'
                                  })
        flavors = ['user']

    # Generate scripts in a "unique" destination directory
    # gmtime([seconds]) -> (tm_year, tm_mon, tm_day, tm_hour, tm_min,
    #                       tm_sec, tm_wday, tm_yday, tm_isdst)

    now = time.gmtime()
    timestamp = '%.2d%.2d%.2d-%.2d%.2d%.2d' % (
        now[2],
        now[1],
        now[0],
        now[3],
        now[4],
        now[5],
        )

    if not langs:

        # Add new languages here

        languages = [(usergen.sh_lang, sh_cmd, usergen.sh_ext),
                     (usergen.python_lang, python_cmd,
                     usergen.python_ext)]
    else:
        languages = []

        # check arguments

        for lang in langs:
            if lang == 'sh':
                interpreter = sh_cmd
                extension = usergen.sh_ext
            elif lang == 'python':
                interpreter = python_cmd
                extension = usergen.python_ext
            else:
                output_objects.append({'object_type': 'warning', 'text'
                        : 'Unknown script language: %s - ignoring!'
                         % lang})
                continue

            languages.append((lang, interpreter, extension))

    if not languages:
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'No valid languages specified - aborting script generation'
                              })
        return (output_objects, returnvalues.CLIENT_ERROR)

    for flavor in flavors:
        script_dir = '%s-%s-scripts-%s' % (configuration.short_title, flavor, timestamp)
        dest_dir = '%s%s' % (base_dir, script_dir)

        if not os.path.isdir(dest_dir):
            try:
                os.mkdir(dest_dir)
            except Exception, exc:
                output_objects.append({'object_type': 'error_text',
                        'text'
                        : 'Failed to create destination directory (%s) - aborting script generation'
                         % exc})
                return (output_objects, returnvalues.SYSTEM_ERROR)

        for (lang, _, _) in languages:
            output_objects.append({'object_type': 'text', 'text'
                                  : 'Generating %s %s scripts in the %s subdirectory of your %s home directory'
                                   % (lang, flavor, script_dir, configuration.short_title )})

        # Generate all scripts

        if flavor == 'user':
            for op in usergen.script_ops:
                generator = 'usergen.generate_%s' % op
                eval(generator)(languages, dest_dir)

            if usergen.shared_lib:
                usergen.generate_lib(usergen.script_ops, languages,
                        dest_dir)

            if usergen.test_script:
                usergen.generate_test(languages, dest_dir)
        elif flavor == 'resource':
            for op in vgridgen.script_ops_single_arg:
                vgridgen.generate_single_argument(op[0], op[1],
                        languages, dest_dir)
            for op in vgridgen.script_ops_single_upload_arg:
                vgridgen.generate_single_argument_upload(op[0], op[1],
                        op[2], languages, dest_dir)
            for op in vgridgen.script_ops_two_args:
                vgridgen.generate_two_arguments(op[0], op[1], op[2],
                        languages, dest_dir)
            for op in vgridgen.script_ops_ten_args:
                vgridgen.generate_ten_arguments(op[0], op[1], op[2], op[3],
                                                  op[4], op[5], op[6], op[7],
                                                  op[8], op[9], op[10],
                                                  languages, dest_dir)
        else:
            output_objects.append({'object_type': 'warning_text', 'text'
                                  : 'Unknown flavor: %s' % flavor})
            continue

        # Always include license conditions file
        
        usergen.write_license(dest_dir)
        
        output_objects.append({'object_type': 'text', 'text': '... Done'
                              })
        output_objects.append({'object_type': 'text', 'text'
                              : '%s %s scripts are now available in your %s home directory:'
                               % (configuration.short_title, flavor, configuration.short_title)})
        output_objects.append({'object_type': 'link', 'text'
                              : 'View directory', 'destination'
                              : 'fileman.py?path=%s/' % script_dir})

        # Create zip from generated dir

        output_objects.append({'object_type': 'text', 'text'
                              : 'Generating zip archive of the %s %s scripts'
                               % (configuration.short_title, flavor)})

        script_zip = script_dir + '.zip'
        dest_zip = '%s%s' % (base_dir, script_zip)
        # Force compression
        zip_file = zipfile.ZipFile(dest_zip, 'w', zipfile.ZIP_DEFLATED)

        # Directory write is not supported - add each file manually

        for script in os.listdir(dest_dir):
            zip_file.write(dest_dir + os.sep + script, script_dir
                            + os.sep + script)

        # Preserve executable flag in accordance with:
        # http://mail.python.org/pipermail/pythonmac-sig/2005-March/013491.html

        for zinfo in zip_file.filelist:
            zinfo.create_system = 3

        zip_file.close()

        # Verify CRC

        zip_file = zipfile.ZipFile(dest_zip, 'r')
        err = zip_file.testzip()
        zip_file.close()
        if err:
            output_objects.append({'object_type': 'error_text', 'text'
                                  : 'Zip file integrity check failed! (%s)'
                                   % err})
            status = returnvalues.SYSTEM_ERROR
            continue

        output_objects.append({'object_type': 'text', 'text': '... Done'
                              })
        output_objects.append({'object_type': 'text', 'text'
                              : 'Zip archive of the %s %s scripts are now available in your %s home directory'
                               % (configuration.short_title, flavor, configuration.short_title)})
        output_objects.append({'object_type': 'link', 'text'
                              : 'Download zip archive', 'destination'
                              : os.path.join('..', client_dir,
                              script_zip)})
Пример #42
0
        </style>
        ''' % (visibility_mods % {'main_class': main_class})

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

    base_dir = os.path.abspath(os.path.join(base_dir, target_dir)) + os.sep

    if not os.path.isdir(base_dir):
        logger.error('%s called on missing base_dir: %s' % (op_name, base_dir))
        output_objects.append({'object_type': 'error_text', 'text':
                               'No such %s!' % page_title.lower()
                               })
        return (output_objects, returnvalues.CLIENT_ERROR)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = page_title
    title_entry['skipwidgets'] = not widgets
    title_entry['skipuserstyle'] = not userstyle
    user_settings = title_entry.get('user_settings', {})

    open_button_id = 'open_fancy_upload'
    form_method = 'post'
    csrf_limit = get_csrf_limit(configuration)
    fill_helpers = {'dest_dir': current_dir + os.sep, 'share_id': share_id,
                    'flags': flags, 'tmp_flags': flags, 'long_set':
                    long_list(flags), 'recursive_set': recursive(flags),
                    'all_set': all(flags), 'fancy_open': open_button_id,
                    'fancy_dialog': fancy_upload_html(configuration),
                    'form_method': form_method, 'csrf_field': csrf_field,
                    'csrf_limit': csrf_limit}
Пример #43
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, op_menu=False)
    defaults = signature()[1]
    (validate_status, accepted) = validate_input(user_arguments_dict,
            defaults, output_objects, allow_rejects=False)
    if not validate_status:
        logger.warning('%s invalid input: %s' % (op_name, accepted))
        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 certificate request' % configuration.short_title
    title_entry['skipmenu'] = True
    output_objects.append({'object_type': 'header', 'text'
                          : '%s certificate request' % \
                            configuration.short_title 
                           })

    admin_email = configuration.admin_email
    smtp_server = configuration.smtp_server
    user_pending = os.path.abspath(configuration.user_pending)

    # force name to capitalized form (henrik karlsen -> Henrik Karlsen)
    # please note that we get utf8 coded bytes here and title() treats such
    # chars as word termination. Temporarily force to unicode.

    raw_name = accepted['cert_name'][-1].strip() 
    try:
        cert_name = force_utf8(force_unicode(raw_name).title())
    except Exception:
        cert_name = raw_name.title()
    country = accepted['country'][-1].strip().upper()
    state = accepted['state'][-1].strip().title()
    org = accepted['org'][-1].strip()

    # lower case email address

    email = accepted['email'][-1].strip().lower()
    password = accepted['password'][-1]
    verifypassword = accepted['verifypassword'][-1]

    # keep comment to a single line

    comment = accepted['comment'][-1].replace('\n', '   ')

    # single quotes break command line format - remove

    comment = comment.replace("'", ' ')

    if password != verifypassword:
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'Password and verify password are not identical!'
                              })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # TODO: move this check to conf?

    if not forced_org_email_match(org, email, configuration):
        output_objects.append({'object_type': 'error_text', 'text'
                              : '''Illegal email and organization combination:
Please read and follow the instructions in red on the request page!
If you are a student with only a @*.ku.dk address please just use KU as
organization. As long as you state that you want the certificate for course
purposes in the comment field, you will be given access to the necessary
resources anyway.
'''})
        return (output_objects, returnvalues.CLIENT_ERROR)

    user_dict = {
        'full_name': cert_name,
        'organization': org,
        'state': state,
        'country': country,
        'email': email,
        'comment': comment,
        'password': base64.b64encode(password),
        'expire': int(time.time() + cert_valid_days * 24 * 60 * 60),
        'openid_names': [],
        }
    fill_distinguished_name(user_dict)
    user_id = user_dict['distinguished_name']
    user_dict['authorized'] = (user_id == client_id)
    if configuration.user_openid_providers and configuration.user_openid_alias:
        user_dict['openid_names'] += \
                                  [user_dict[configuration.user_openid_alias]]
    logger.info('got reqcert request: %s' % user_dict)

    # For testing only
    
    if cert_name.upper().find('DO NOT SEND') != -1:
        output_objects.append({'object_type': 'text', 'text'
                          : "Test request ignored!"})
        return (output_objects, returnvalues.OK)

    req_path = None
    try:
        (os_fd, req_path) = tempfile.mkstemp(dir=user_pending)
        os.write(os_fd, dumps(user_dict))
        os.close(os_fd)
    except Exception, err:
        logger.error('Failed to write certificate request to %s: %s'
                      % (req_path, err))
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'Request could not be sent to grid administrators. Please contact them manually on %s if this error persists.'
                               % admin_email})
        return (output_objects, returnvalues.SYSTEM_ERROR)
Пример #44
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 Resource Monitor' % label
    (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)

    meta = '''<meta http-equiv="refresh" content="%s" />
''' % configuration.sleep_secs
    add_import = '''
<script type="text/javascript" src="/images/js/jquery.tablesorter.js"></script>
    '''
    add_init = ''
    add_ready = '''
          // table initially sorted by col. 1 (name)
          var sortOrder = [[1,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;
          }
          $("table.monitor").tablesorter({widgets: ["zebra"],
                                          textExtraction: imgTitle,
                                         });
          $("table.monitor").each(function () {
              try {
                  $(this).trigger("sorton", [sortOrder]);
              } catch(err) {
                  /* tablesorter chokes on empty tables - just continue */
              }
          });
    '''
    title_entry['script']['advanced'] += add_import
    title_entry['script']['init'] += add_init
    title_entry['script']['ready'] += add_ready
    title_entry['meta'] = meta

    vgrid_access = user_vgrid_access(configuration, client_id)
    vgrid_list = accepted['vgrid_name']
    if all_vgrids in accepted['vgrid_name']:
        vgrid_list = [i for i in vgrid_list if all_vgrids != i]\
            + vgrid_access

    # Force list to sequence of unique entries

    for vgrid_name in set(vgrid_list):
        html = ''
        if not vgrid_is_owner_or_member(vgrid_name, client_id,
                                        configuration):
            output_objects.append({'object_type': 'error_text', 'text':
                                   '''You must be an owner or member of %s %s
to access the monitor.''' % (vgrid_name, label)})
            return (output_objects, returnvalues.CLIENT_ERROR)

        monitor_file = os.path.join(configuration.vgrid_home, vgrid_name,
                                    '%s.html' % configuration.vgrid_monitor)
        try:
            monitor_fd = open(monitor_file, 'r')
            past_header = False
            for line in monitor_fd:
                if -1 != line.find('end of raw header'):
                    past_header = True
                    continue
                if not past_header:
                    continue
                if -1 != line.find('begin raw footer:'):
                    break
                html += str(line)
            monitor_fd.close()
        except Exception, exc:
            output_objects.append({'object_type': 'error_text', 'text':
                                   'Error reading %s monitor page (%s)' %
                                   (label, exc)})
            return (output_objects, returnvalues.SYSTEM_ERROR)

        output_objects.append({'object_type': 'html_form', 'text': html})
Пример #45
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')
    title_entry['text'] = 'Show Runtime Environment Details'
    (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)
    re_name = accepted['re_name'][-1]

    output_objects.append({
        'object_type': 'header',
        'text': 'Show runtime environment details'
    })

    if not valid_dir_input(configuration.re_home, re_name):
        logger.warning(
            "possible illegal directory traversal attempt re_name '%s'" %
            re_name)
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Illegal runtime environment name: "%s"' % re_name
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    if not is_runtime_environment(re_name, configuration):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            "'%s' is not an existing runtime environment!" % re_name
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Runtime environment details'

    (re_dict, msg) = get_re_dict(re_name, configuration)
    if not re_dict:
        output_objects.append({
            'object_type': 'error_text',
            'text': 'Could not read details for "%s"' % msg
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # Set providers explicitly after build_reitem_object to avoid import loop
    re_item = build_reitem_object(configuration, re_dict)
    re_name = re_item['name']
    re_item['providers'] = resources_using_re(configuration, re_name)
    re_item['resource_count'] = len(re_item['providers'])

    output_objects.append(re_item)

    return (output_objects, returnvalues.OK)
Пример #46
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')
    label = "%s" % configuration.site_vgrid_label
    title_entry['text'] = "%s Management" % label
    (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)

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

    if not operation in allowed_operations:
        output_objects.append({
            'object_type':
            'error_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))
    vgrid_items, active_vgrid_links = [], []
    member_list = {
        'object_type': 'vgrid_list',
        'vgrids': vgrid_items,
        'components': active_vgrid_links
    }

    # Check if user wants advanced VGrid component links

    user_settings = title_entry.get('user_settings', {})
    collaboration_links = user_settings.get('SITE_COLLABORATION_LINKS',
                                            'default')
    if not collaboration_links in configuration.site_collaboration_links or \
            collaboration_links == 'default':
        active_vgrid_links += configuration.site_default_vgrid_links
    elif collaboration_links == 'advanced':
        active_vgrid_links += configuration.site_advanced_vgrid_links

    # General fill helpers including CSRF fields

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

    if operation in show_operations:

        # jquery support for tablesorter and confirmation on request and leave
        # table initially sorted by col. 2 (admin), then 3 (member), then 0 (name)

        # NOTE: We distinguish between caching on page load and forced refresh
        refresh_helper = 'ajax_vgridman("%s", %s, %%s)'
        refresh_call = refresh_helper % (label, active_vgrid_links)
        table_spec = {
            'table_id': 'vgridtable',
            'sort_order': '[[2,1],[3,1],[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)
        })

        # Append VGrid alias note if custom
        if label != 'VGrid':
            long_label = '%ss (i.e. VGrids)' % label
        else:
            long_label = "%ss" % label

        output_objects.append({
            'object_type': 'header',
            'text': "%s" % long_label
        })
        output_objects.append({
            'object_type':
            'text',
            'text':
            '''%ss share files, a number of collaboration
tools and resources. Members can access web pages, files, tools and resources.
Owners can additionally edit pages, as well as add and remove members or
resources.''' % label
        })

        if label != 'VGrid':
            output_objects.append({
                'object_type':
                'text',
                'text':
                """Please note that for historical reasons
%ss are also referred to as VGrids in some contexts.""" % label
            })

        output_objects.append({
            'object_type': 'sectionheader',
            'text': '%ss managed on this server' % label
        })

        # Helper forms for requests and removes

        for post_type in ["vgridowner", "vgridmember"]:
            target_op = 'sendrequestaction'
            csrf_token = make_csrf_token(configuration, form_method, target_op,
                                         client_id, csrf_limit)
            helper = html_post_helper(
                'req%s' % post_type, '%s.py' % target_op, {
                    'vgrid_name': '__DYNAMIC__',
                    'request_type': post_type,
                    'request_text': '',
                    csrf_field: csrf_token
                })
            output_objects.append({'object_type': 'html_form', 'text': helper})
        for post_type in ["vgridowner", "vgridmember"]:
            target_op = 'rm%s' % post_type
            csrf_token = make_csrf_token(configuration, form_method, target_op,
                                         client_id, csrf_limit)
            helper = html_post_helper(
                target_op, '%s.py' % target_op, {
                    'vgrid_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': '%ss' % label,
            'default_entries': default_pager_entries
        })

    if operation in list_operations:
        logger.info("get vgrid map with caching %s" % caching)
        vgrid_map = get_vgrid_map(configuration, caching=caching)
        member_list['pending_updates'] = False
        if caching:
            modified_vgrids, _ = check_vgrids_modified(configuration)
            if modified_vgrids:
                logger.info("pending cache updates: %s" % modified_vgrids)
                member_list['pending_updates'] = True
            else:
                logger.info("no pending cache updates")

        vgrid_list = vgrid_map[VGRIDS].keys()

        # Iterate through vgrids and print details for each

        if 'monitor' in active_vgrid_links:
            vgrid_list = [all_vgrids] + vgrid_list
        else:
            vgrid_list.remove(default_vgrid)
        # User vgrid_list here to include default and all mangling above
        for vgrid_name in vgrid_list:
            vgrid_dict = vgrid_map[VGRIDS].get(vgrid_name, {})
            settings_dict = dict(vgrid_dict.get(SETTINGS, []))
            # Mark and show hidden vgrids if owner or member and hide otherwise
            view_icon, hidden_status = "infolink", " "
            if settings_dict.get('hidden', False):
                if client_id in vgrid_dict[OWNERS] + vgrid_dict[MEMBERS]:
                    logger.debug("show hidden vgrid %s for participant" %
                                 vgrid_name)
                    view_icon, hidden_status = "shadeinfolink", " hidden "
                else:
                    logger.debug("skip hidden vgrid %s" % vgrid_name)
                    continue
            vgrid_obj = {'object_type': 'vgrid', 'name': vgrid_name}

            if vgrid_name == default_vgrid:

                # Everybody is member and allowed to see statistics, Noone
                # can own it or leave it. Do not add any page links.

                vgrid_obj['privatemonitorlink'] = {
                    'object_type': 'link',
                    'destination':
                    'showvgridmonitor.py?vgrid_name=%s' % vgrid_name,
                    'class': 'monitorlink iconspace',
                    'title': 'View %s monitor' % vgrid_name,
                    'text': 'View'
                }
                vgrid_obj['memberlink'] = {
                    'object_type':
                    'link',
                    'destination':
                    '',
                    'class':
                    'infolink iconspace',
                    'title':
                    'Every user is member of the %s %s' %
                    (default_vgrid, label),
                    'text':
                    ''
                }
                vgrid_obj['administratelink'] = {
                    'object_type': 'link',
                    'destination': '',
                    'class': 'infolink iconspace',
                    'title': 'Nobody owns the %s %s' % (default_vgrid, label),
                    'text': ''
                }
                vgrid_obj['viewvgridlink'] = {
                    'object_type': 'link',
                    'destination': 'viewvgrid.py?vgrid_name=%s' % vgrid_name,
                    'class': 'infolink iconspace',
                    'title':
                    'View details for the %s %s' % (default_vgrid, label),
                    'text': ''
                }
                vgrid_items.append(vgrid_obj)
                continue
            elif vgrid_name == all_vgrids:

                # Only show global monitor link for all_vgrids, Noone
                # can own it or leave it. Do not add any page links.

                vgrid_obj['privatemonitorlink'] = {
                    'object_type': 'link',
                    'destination':
                    'showvgridmonitor.py?vgrid_name=%s' % vgrid_name,
                    'class': 'monitorlink iconspace',
                    'title': 'View global monitor',
                    'text': 'View'
                }
                vgrid_obj['memberlink'] = {
                    'object_type': 'link',
                    'destination': '',
                    'class': 'infolink iconspace',
                    'title': 'Not a real %s - only for global monitor' % label,
                    'text': ''
                }
                vgrid_obj['administratelink'] = {
                    'object_type': 'link',
                    'destination': '',
                    'class': '',
                    'title': '',
                    'text': ''
                }
                vgrid_obj['viewvgridlink'] = {
                    'object_type': 'link',
                    'destination': '',
                    'class': 'infolink iconspace',
                    'title': 'Not a real %s - only for global monitor' % label,
                    'text': ''
                }
                vgrid_items.append(vgrid_obj)
                continue

            # links for everyone: public pages and membership request

            vgrid_obj['publicscmlink'] = {
                'object_type':
                'link',
                'destination':
                '%s/vgridpublicscm/%s' %
                (configuration.migserver_http_url, vgrid_name),
                'class':
                'scmlink public iconspace',
                'title':
                'Open %s public SCM' % vgrid_name,
                'text':
                'Open'
            }
            vgrid_obj['publictrackerlink'] = {
                'object_type':
                'link',
                'destination':
                '%s/vgridpublictracker/%s' %
                (configuration.migserver_http_url, vgrid_name),
                'class':
                'trackerlink public iconspace',
                'title':
                'Open %s public tracker' % vgrid_name,
                'text':
                'Open'
            }
            vgrid_obj['enterpubliclink'] = {
                'object_type':
                'link',
                'destination':
                '%s/vgrid/%s/path/index.html' %
                (configuration.migserver_http_url, vgrid_name),
                'class':
                'urllink member iconspace',
                'title':
                'View public %s web page' % vgrid_name,
                'text':
                'View'
            }

            # Link to show vgrid details

            vgrid_obj['viewvgridlink'] = \
                {'object_type': 'link',
                 'destination': 'viewvgrid.py?vgrid_name=%s' %
                 vgrid_name,
                 'class': '%s iconspace' % view_icon,
                 'title': 'View details for the %s%s%s'
                 % (vgrid_name, hidden_status, label),
                 'text': ''}

            # link to become member: overwritten later for members

            vgrid_obj['memberlink'] = {
                'object_type':
                'link',
                'destination':
                "javascript: confirmDialog(%s, '%s', '%s', %s);" %
                ('reqvgridmember', "Request membership of " + vgrid_name +
                 ":<br/>\nPlease write a message to the owners (field below).",
                 'request_text', "{vgrid_name: '%s'}" % vgrid_name),
                'class':
                'addlink iconspace',
                'title':
                'Request membership of %s' % vgrid_name,
                'text':
                ''
            }

            # link to become owner: overwritten later for owners

            vgrid_obj['administratelink'] = {
                'object_type':
                'link',
                'destination':
                "javascript: confirmDialog(%s, '%s', '%s', %s);" %
                ('reqvgridowner', "Request ownership of " + vgrid_name +
                 ":<br/>\nPlease write a message to the owners (field below).",
                 'request_text', "{vgrid_name: '%s'}" % vgrid_name),
                'class':
                'addadminlink iconspace',
                'title':
                'Request ownership of %s' % vgrid_name,
                'text':
                ''
            }

            # members/owners are allowed to view private pages and monitor

            if client_id in vgrid_dict[OWNERS] + vgrid_dict[MEMBERS]:
                vgrid_obj['enterprivatelink'] = {
                    'object_type': 'link',
                    'destination': '../vgrid/%s/path/index.html' % vgrid_name,
                    'class': 'urllink owner iconspace',
                    'title': 'View private %s web page' % vgrid_name,
                    'text': 'View'
                }
                vgrid_obj['sharedfolderlink'] = {
                    'object_type': 'link',
                    'destination': 'fileman.py?path=%s/' % vgrid_name,
                    'class': 'sharedfolderlink iconspace',
                    'title': 'Open shared %s folder' % vgrid_name,
                    'text': 'Open'
                }
                vgrid_obj['memberscmlink'] = {
                    'object_type': 'link',
                    'destination': '/vgridscm/%s' % vgrid_name,
                    'class': 'scmlink member iconspace',
                    'title': 'View %s members scm' % vgrid_name,
                    'text': 'View'
                }
                vgrid_obj['membertrackerlink'] = {
                    'object_type': 'link',
                    'destination': '/vgridtracker/%s' % vgrid_name,
                    'class': 'trackerlink member iconspace',
                    'title': 'View %s members tracker' % vgrid_name,
                    'text': 'View'
                }
                vgrid_obj['privateforumlink'] = {
                    'object_type': 'link',
                    'destination': 'vgridforum.py?vgrid_name=%s' % vgrid_name,
                    'class': 'forumlink iconspace',
                    'title': 'Open %s private forum' % vgrid_name,
                    'text': 'Open'
                }
                vgrid_obj['privateworkflowslink'] = {
                    'object_type': 'link',
                    'destination':
                    'vgridworkflows.py?vgrid_name=%s' % vgrid_name,
                    'class': 'workflowslink iconspace',
                    'title': 'Open %s private workflows' % vgrid_name,
                    'text': 'Open'
                }
                vgrid_obj['privatemonitorlink'] = {
                    'object_type': 'link',
                    'destination':
                    'showvgridmonitor.py?vgrid_name=%s' % vgrid_name,
                    'class': 'monitorlink iconspace',
                    'title': 'View %s monitor' % vgrid_name,
                    'text': 'View'
                }

                # to leave this VGrid (remove ourselves). Note that we are
                # going to overwrite the link later for owners.

                vgrid_obj['memberlink'].update({
                    'destination':
                    "javascript: confirmDialog(%s, '%s', %s, %s);" %
                    ('rmvgridmember', "Really leave " + vgrid_name + "?",
                     'undefined', "{vgrid_name: '%s'}" % vgrid_name),
                    'class':
                    'removelink iconspace',
                    'title':
                    'Leave %s members' % vgrid_name,
                })

            # owners are allowed to edit pages and administrate

            if client_id in vgrid_dict[OWNERS]:
                vgrid_obj['ownerscmlink'] = {
                    'object_type': 'link',
                    'destination': '/vgridownerscm/%s' % vgrid_name,
                    'class': 'scmlink owner iconspace',
                    'title': 'View %s owners scm' % vgrid_name,
                    'text': 'View'
                }
                vgrid_obj['ownertrackerlink'] = {
                    'object_type': 'link',
                    'destination': '/vgridownertracker/%s' % vgrid_name,
                    'class': 'trackerlink owner iconspace',
                    'title': 'View %s owners tracker' % vgrid_name,
                    'text': 'View'
                }

                # correct the link to leave the VGrid

                vgrid_obj['memberlink'].update({
                    'destination':
                    "javascript: confirmDialog(%s, '%s', %s, %s);" %
                    ('rmvgridowner', "Really leave " + vgrid_name + "?",
                     'undefined', "{vgrid_name: '%s'}" % vgrid_name),
                    'class':
                    'removeadminlink iconspace',
                    'title':
                    'Leave %s owners' % vgrid_name
                })

                # add more links: administrate and edit pages

                vgrid_obj['administratelink'] = {
                    'object_type': 'link',
                    'destination': 'adminvgrid.py?vgrid_name=%s' % vgrid_name,
                    'class': 'adminlink iconspace',
                    'title': 'Administrate %s' % vgrid_name,
                    'text': ''
                }
                vgrid_obj['editprivatelink'] = {
                    'object_type': 'link',
                    'destination':
                    'fileman.py?path=private_base/%s/' % vgrid_name,
                    'class': 'editlink owner iconspace',
                    'title': 'Edit private %s web page' % vgrid_name,
                    'text': 'Edit'
                }
                vgrid_obj['editpubliclink'] = {
                    'object_type': 'link',
                    'destination':
                    'fileman.py?path=public_base/%s/' % vgrid_name,
                    'class': 'editlink member iconspace',
                    'title': 'Edit public %s web page' % vgrid_name,
                    'text': 'Edit'
                }

            vgrid_items.append(vgrid_obj)

    if operation == "show":
        # insert dummy placeholder to build table
        vgrid_obj = {'object_type': 'vgrid', 'name': default_vgrid}
        for field in active_vgrid_links:
            vgrid_obj[field] = ''
        vgrid_items.append(vgrid_obj)

    output_objects.append(member_list)

    if operation in show_operations:
        user_map = get_full_user_map(configuration)
        user_dict = user_map.get(client_id, None)
        # Optional limitation of create vgrid permission
        if user_dict and vgrid_create_allowed(configuration, user_dict):
            output_objects.append({
                'object_type': 'sectionheader',
                'text': 'Additional %ss' % label
            })

            output_objects.append({
                'object_type':
                'text',
                'text':
                '''Please enter a name for the new %(vgrid_label)s to add,
using slashes to specify nesting. I.e. if you own a %(vgrid_label)s called ABC,
you can create a sub-%(vgrid_label)s called DEF by entering ABC/DEF below.
''' % fill_helpers
            })

            target_op = 'createvgrid'
            csrf_token = make_csrf_token(configuration, form_method, target_op,
                                         client_id, csrf_limit)
            fill_helpers.update({
                'target_op': target_op,
                'csrf_token': csrf_token
            })
            output_objects.append({
                'object_type':
                'html_form',
                'text':
                '''
        <form method="%(form_method)s" action="%(target_op)s.py">
        <input type="hidden" name="%(csrf_field)s" value="%(csrf_token)s" />
        <input class="p60width" type="text" name="vgrid_name" required 
        pattern="[a-zA-Z0-9 /_.-]*"
        title="unique name of ASCII letters and digits separated only by underscores, periods, spaces and hyphens. Slashes are additionally allowed when creating nested sub-%(vgrid_label)ss" />
        <input type="hidden" name="output_format" value="html" />
        <input type="submit" value="Create %(vgrid_label)s" />
        </form>
     ''' % fill_helpers
            })

        output_objects.append({
            'object_type': 'sectionheader',
            'text': 'Request Access to %ss' % label
        })

        output_objects.append({
            'object_type':
            'text',
            'text':
            '''You can request access to %(vgrid_label)ss using the individual
plus-icons above directly or by entering the name of the %(vgrid_label)s to
request access to, what kind of access and an optional message to the admins
below''' % fill_helpers
        })
        target_op = 'sendrequestaction'
        csrf_token = make_csrf_token(configuration, form_method, target_op,
                                     client_id, csrf_limit)
        fill_helpers.update({'target_op': target_op, 'csrf_token': csrf_token})
        output_objects.append({
            'object_type':
            'html_form',
            'text':
            '''
        <form method="%(form_method)s" action="%(target_op)s.py">
        <input type="hidden" name="%(csrf_field)s" value="%(csrf_token)s" />
        <input class="p60width" type="text" name="vgrid_name" required 
        pattern="[a-zA-Z0-9 /_.-]*"
        title="the name of an existing %(vgrid_label)s" />
        <select class="styled-select html-select" name="request_type">
            <option value="vgridmember">membership</option> 
            <option value="vgridowner">ownership</option>
        </select>
        <br/>
        <input class="p60width" type="text" name="request_text" required />
        <input type="hidden" name="output_format" value="html" />
        <input type="submit" value="Request %(vgrid_label)s access" />
        </form>
    ''' % fill_helpers
        })

    logger.info("%s %s end for %s" % (op_name, operation, client_id))
    return (output_objects, status)
Пример #47
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)
    client_dir = client_id_dir(client_id)
    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)

    vgrid_name = accepted['vgrid_name'][-1].strip()

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

    # No owner check here so we need to specifically check for illegal
    # directory access

    reserved_names = (default_vgrid, any_vgrid, all_vgrids)
    if vgrid_name in reserved_names or \
           not valid_dir_input(configuration.vgrid_home, vgrid_name):
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'Illegal vgrid_name: %s' % vgrid_name})
        logger.warning("""createvgrid possible illegal directory access
attempt by '%s': vgrid_name '%s'""" % (client_id, vgrid_name))
        return (output_objects, returnvalues.CLIENT_ERROR)

    user_map = get_full_user_map(configuration)
    user_dict = user_map.get(client_id, None)
    # Optional limitation of create vgrid permission
    if not user_dict or \
           not vgrid_create_allowed(configuration, user_dict):
        logger.warning("user %s is not allowed to create %ss!" % \
                       (client_id, configuration.site_vgrid_label))
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : 'Only privileged users can create %ss' % \
             configuration.site_vgrid_label})
        return (output_objects, returnvalues.CLIENT_ERROR)

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

    base_dir = os.path.abspath(os.path.join(configuration.vgrid_home,
                               vgrid_name)) + os.sep
    public_base_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name)) + os.sep
    public_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name, '.vgridscm')) + os.sep
    public_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name, '.vgridtracker')) + os.sep
    private_base_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name)) + os.sep
    private_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridscm')) + os.sep
    private_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridtracker')) + os.sep
    private_forum_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridforum')) + os.sep
    vgrid_files_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name)) + os.sep
    vgrid_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name, '.vgridscm')) + os.sep
    vgrid_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name, '.vgridtracker')) + os.sep

    # does vgrid exist?

    if os.path.isdir(base_dir):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : '%s %s cannot be created because it already exists!'
             % (configuration.site_vgrid_label, vgrid_name)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # verify that client is owner of imada or imada/topology if trying to
    # create imada/topology/test

    vgrid_name_list = vgrid_name.split('/')
    vgrid_name_list_length = len(vgrid_name_list)
    if vgrid_name_list_length <= 0:
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'vgrid_name not specified?'})
        return (output_objects, returnvalues.SYSTEM_ERROR)
    elif vgrid_name_list_length == 1:

        # anyone can create base vgrid

        new_base_vgrid = True
    else:
        new_base_vgrid = False
        vgrid_name_without_last_fragment = \
            '/'.join(vgrid_name_list[0:vgrid_name_list_length - 1])
        parent_base = os.path.dirname(base_dir.rstrip(os.sep))
        if not os.path.isdir(parent_base):
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : 'Parent %s %s does not exist!' % \
                 (configuration.site_vgrid_label,
                  vgrid_name_without_last_fragment)
                 })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not vgrid_is_owner(vgrid_name_without_last_fragment,
                              client_id, configuration):
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : 'You must own a parent %s to create a sub vgrid' % \
                 configuration.site_vgrid_label
                 })
            return (output_objects, returnvalues.CLIENT_ERROR)

    # make sure all dirs can be created (that a file or directory with the same
    # name do not exist prior to the vgrid creation)

    try_again_string = \
        """%s cannot be created, a file or directory exists with the same
name, please try again with a new name!""" % configuration.site_vgrid_label
    if os.path.exists(public_base_dir):
        output_objects.append({'object_type': 'error_text', 'text'
                              : try_again_string})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if os.path.exists(private_base_dir):
        output_objects.append({'object_type': 'error_text', 'text'
                              : try_again_string})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if os.path.exists(vgrid_files_dir):
        output_objects.append({'object_type': 'error_text', 'text'
                              : try_again_string})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # create directory to store vgrid files

    try:
        os.mkdir(base_dir)
    except Exception, exc:
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : """Could not create %(_label)s directory, remember to create
parent %(_label)s before creating a sub-%(_label)s.""" % \
             {'_label': configuration.site_vgrid_label}
             })
        return (output_objects, returnvalues.CLIENT_ERROR)
Пример #48
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'] = 'Delete frozen archive'
    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)

    flavor = accepted['flavor'][-1]

    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)

    if not flavor in freeze_flavors.keys():
        output_objects.append({
            'object_type': 'error_text',
            'text': 'Invalid freeze flavor: %s' % flavor
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    title = freeze_flavors[flavor]['deletefreeze_title']
    output_objects.append({'object_type': 'header', 'text': title})
    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = title

    if not configuration.site_enable_freeze:
        output_objects.append({
            'object_type':
            'text',
            'text':
            '''Freezing archives is disabled on this site.
Please contact the site admins %s if you think it should be enabled.
''' % configuration.admin_email
        })
        return (output_objects, returnvalues.OK)

    freeze_id = accepted['freeze_id'][-1]
    target = accepted['target'][-1]
    path_list = accepted['path']

    if not target in valid_targets:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Invalid delete freeze target: %s' % target
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # NB: the restrictions on freeze_id prevents illegal directory traversal

    if not is_frozen_archive(client_id, freeze_id, configuration):
        logger.error("%s: invalid freeze '%s': %s" %
                     (op_name, client_id, freeze_id))
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            "No such frozen archive: '%s'" % freeze_id
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    (load_status, freeze_dict) = get_frozen_archive(client_id,
                                                    freeze_id,
                                                    configuration,
                                                    checksum_list=[])
    if not load_status:
        logger.error("%s: load failed for '%s': %s" %
                     (op_name, freeze_id, freeze_dict))
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Could not read frozen archive details for %s' % freeze_id
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # Make sure the frozen archive belongs to the user trying to delete it
    if client_id != freeze_dict['CREATOR']:
        logger.error("%s: illegal access attempt for '%s': %s" %
                     (op_name, freeze_id, client_id))
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'You are not the owner of frozen archive "%s"' % freeze_id
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    if freeze_dict.get('FLAVOR', 'freeze') != flavor:
        logger.error("%s: flavor mismatch for '%s': %s vs %s" %
                     (op_name, freeze_id, flavor, freeze_dict))
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'No such %s archive "%s"' % (flavor, freeze_id)
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Prevent user-delete of the frozen archive if configuration forbids it.
    # We exclude any archives in the pending intermediate freeze state.
    # Freeze admins are also excluded from the restrictions.
    state = freeze_dict.get('STATE', keyword_final)
    if state == keyword_updating:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            "Can't change %s archive %s which is currently being updated" %
            (flavor, freeze_id)
        })
        output_objects.append({
            'object_type':
            'link',
            'destination':
            'showfreeze.py?freeze_id=%s;flavor=%s' % (freeze_id, flavor),
            'class':
            'viewarchivelink iconspace genericbutton',
            'title':
            'View details about your %s archive' % flavor,
            'text':
            'View details',
        })
        return (output_objects, returnvalues.CLIENT_ERROR)
    elif state == keyword_final and \
            flavor in configuration.site_permanent_freeze and \
            not client_id in configuration.site_freeze_admins:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            "Can't change %s archives like '%s' yourself due to site policy" %
            (flavor, freeze_id)
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    client_dir = client_id_dir(client_id)
    user_archives = os.path.join(configuration.freeze_home, client_dir)

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

    base_dir = os.path.abspath(os.path.join(user_archives, freeze_id)) + os.sep

    if target == TARGET_ARCHIVE:
        # Delete the entire freeze archive
        (del_status, msg) = delete_frozen_archive(freeze_dict, client_id,
                                                  configuration)

        # If something goes wrong when trying to delete freeze archive
        # freeze_id, an error is displayed.
        if not del_status:
            logger.error("%s: failed for '%s': %s" % (op_name, freeze_id, msg))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Could not remove entire %s archive %s: %s' %
                (flavor, freeze_id, msg)
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)

        # If deletion of frozen archive freeze_id is successful, we just
        # return OK
        else:
            logger.info("%s: successful for '%s': %s" %
                        (op_name, freeze_id, client_id))
            output_objects.append({
                'object_type':
                'text',
                'text':
                'Successfully deleted %s archive: "%s"' % (flavor, freeze_id)
            })
    elif target == TARGET_PATH:
        # Delete individual files in non-final archive
        del_paths = []
        for path in path_list:
            # IMPORTANT: path must be expanded to abs for proper chrooting
            server_path = os.path.join(base_dir, path)
            abs_path = os.path.abspath(server_path)
            if not valid_user_path(configuration, abs_path, base_dir, False):

                # Out of bounds!

                logger.warning(
                    '%s tried to %s del restricted path %s ! ( %s)' %
                    (client_id, op_name, abs_path, path))
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'Not allowed to delete %s - outside archive %s !' %
                    (path, freeze_id)
                })
                continue
            del_paths.append(path)

        (del_status, msg_list) = delete_archive_files(freeze_dict, client_id,
                                                      del_paths, configuration)

        # If something goes wrong when trying to delete files from archive
        # freeze_id, an error is displayed.
        if not del_status:
            logger.error("%s: delete archive file(s) failed for '%s':\n%s" %
                         (op_name, freeze_id, '\n'.join(msg_list)))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Could not remove file(s) from archive %s: %s' %
                (freeze_id, '\n '.join(msg_list))
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)

        # If deletion of files from archive freeze_id is successful, we just
        # return OK
        else:
            logger.info("%s: delete %d files successful for '%s': %s" %
                        (op_name, len(path_list), freeze_id, client_id))
            output_objects.append({
                'object_type':
                'text',
                'text':
                'Successfully deleted %d file(s) from archive: "%s"' %
                (len(path_list), freeze_id)
            })

    # Success - show link to overview
    output_objects.append({
        'object_type': 'link',
        'destination': 'freezedb.py',
        'class': 'infolink iconspace',
        'title': 'Show archives',
        'text': 'Show archives'
    })
    return (output_objects, returnvalues.OK)