コード例 #1
0
ファイル: jobman.py プロジェクト: ucphhpc/migrid
def css_tmpl(configuration, user_settings):
    """Stylesheets to include in the page header"""

    # TODO: can we update style inline to avoid explicit themed_styles?
    css = themed_styles(
        configuration,
        base=['jquery.contextmenu.css', 'jquery.managers.contextmenu.css'],
        user_settings=user_settings)
    return css
コード例 #2
0
ファイル: fileman.py プロジェクト: heromod/migrid
def css_tmpl(configuration):
    """Stylesheets to include in the page header"""
    css = 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'])
    css['advanced'] += '''
<link href="/images/lib/noUiSlider/jquery.nouislider.css"  rel="stylesheet"
    type="text/css" />   
'''
    css['advanced'] += advanced_editor_css_deps()
    return css
コード例 #3
0
ファイル: bailout.py プロジェクト: ucphhpc/migrid
def bailout_helper(configuration,
                   backend,
                   out_obj,
                   title_text="Runtime Error",
                   header_text="Internal Error"):
    """Fall back output helper to init basic emergency output"""
    _logger = configuration.logger
    if out_obj is None:
        out_obj = []
    title = {'object_type': 'title', 'text': title_text}
    # Try hard to display something mildly formatted
    try:
        from shared.html import themed_styles, themed_scripts
        title['style'] = themed_styles(configuration)
        title['script'] = themed_scripts(configuration, logged_in=False)
        # Hide menu to avoid message truncation
        title['skipmenu'] = True
    except Exception, exc:
        _logger.error("failed to provide even basic styling for %s" % backend)
コード例 #4
0
def css_tmpl(configuration, user_settings={}):
    """Stylesheets to include in the page header"""

    # TODO: can we update style inline to avoid explicit themed_styles?
    css = themed_styles(
        configuration,
        advanced=[
            'jquery.contextmenu.css', 'jquery.managers.contextmenu.css',
            'jquery.xbreadcrumbs.css', 'jquery.fmbreadcrumbs.css',
            'jquery.fileupload.css', 'jquery.fileupload-ui.css'
        ],
        skin=['fileupload-ui.custom.css', 'xbreadcrumbs.custom.css'],
        user_settings=user_settings)

    css['advanced'] += '''
<link href="/images/lib/noUiSlider/jquery.nouislider.css"  rel="stylesheet"
    type="text/css" />
<link href="/images/lib/ParaView/Visualizer/main.css" rel="stylesheet"
    type="text/css" />
'''
    css['advanced'] += advanced_editor_css_deps()
    return css
コード例 #5
0
def create_monitor(vgrid_name):
    """Write monitor HTML file for vgrid_name"""

    html_file = os.path.join(configuration.vgrid_home, vgrid_name,
                             '%s.html' % configuration.vgrid_monitor)

    print 'collecting statistics for VGrid %s' % vgrid_name
    sleep_secs = configuration.sleep_secs
    slackperiod = configuration.slackperiod
    now = time.asctime(time.localtime())

    html_vars = {
        'sleep_secs': sleep_secs,
        'vgrid_name': vgrid_name,
        'logo_url': '/images/logo.jpg',
        'now': now,
        'short_title': configuration.short_title,
    }

    monitor_meta = '''<meta http-equiv="refresh" content="%(sleep_secs)s" />
''' % html_vars
    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 */
              }
          });
    '''
    monitor_js = '''
%s

<script type="text/javascript" >

%s

$(document).ready(function() {
%s
          }
);
</script>
''' % (add_import, add_init, add_ready)

    # User default site style
    style_helpers = themed_styles(configuration)
    script_helpers = themed_scripts(configuration)
    script_helpers['advanced'] += add_import
    script_helpers['init'] += add_init
    script_helpers['ready'] += add_ready
    html = get_xgi_html_header(
        configuration,
        '%(short_title)s Monitor, VGrid %(vgrid_name)s' % html_vars,
        '',
        html=True,
        meta=monitor_meta,
        style_map=style_helpers,
        script_map=script_helpers,
        frame=False,
        menu=False,
        widgets=False,
        userstyle=False,
    )
    html += \
        '''
<!-- end of raw header: this line is used by showvgridmonitor -->
<h1>Statistics/monitor for the %(vgrid_name)s VGrid</h1>
<div class="generatornote smallcontent">
This page was generated %(now)s (automatic refresh every %(sleep_secs)s secs).
</div>
'''\
         % html_vars

    # loop and get totals

    parse_count = 0
    queued_count = 0
    frozen_count = 0
    executing_count = 0
    finished_count = 0
    failed_count = 0
    retry_count = 0
    canceled_count = 0

    cpucount_requested = 0
    cpucount_done = 0
    nodecount_requested = 0
    nodecount_done = 0
    cputime_requested = 0
    cputime_done = 0
    used_walltime = 0
    disk_requested = 0
    disk_done = 0
    memory_requested = 0
    memory_done = 0
    runtimeenv_dict = {'': 0}
    runtimeenv_requested = 0
    runtimeenv_done = 0

    number_of_jobs = 0
    up_count = 0
    down_count = 0
    slack_count = 0

    job_assigned = 0
    job_assigned_cpus = 0

    gstat = GridStat(configuration, logger)

    runtimeenv_dict = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                      'RUNTIMEENVIRONMENT', {})

    parse_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), 'PARSE')
    queued_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), 'QUEUED')
    frozen_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), 'FROZEN')
    executing_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                      'EXECUTING')
    failed_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), 'FAILED')
    retry_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), 'RETRY')
    canceled_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                     'CANCELED')
    expired_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), 'EXPIRED')
    finished_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                     'FINISHED')

    nodecount_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                          'NODECOUNT_REQ')
    nodecount_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                     'NODECOUNT_DONE')
    cputime_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                        'CPUTIME_REQ')
    cputime_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                   'CPUTIME_DONE')

    used_walltime = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                    'USED_WALLTIME')

    if (used_walltime == 0):
        used_walltime = datetime.timedelta(0)

    used_walltime = format_timedelta(used_walltime)

    disk_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                     'DISK_REQ')
    disk_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(), 'DISK_DONE')
    memory_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                       'MEMORY_REQ')
    memory_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                  'MEMORY_DONE')
    cpucount_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                         'CPUCOUNT_REQ')
    cpucount_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                    'CPUCOUNT_DONE')
    runtimeenv_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                           'RUNTIMEENVIRONMENT_REQ')
    runtimeenv_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(),
                                      'RUNTIMEENVIRONMENT_DONE')

    number_of_jobs = parse_count
    number_of_jobs += queued_count
    number_of_jobs += frozen_count
    number_of_jobs += expired_count
    number_of_jobs += canceled_count
    number_of_jobs += failed_count
    number_of_jobs += executing_count
    number_of_jobs += finished_count
    number_of_jobs += retry_count

    html_vars = {
        'parse_count': parse_count,
        'queued_count': queued_count,
        'frozen_count': frozen_count,
        'executing_count': executing_count,
        'failed_count': failed_count,
        'retry_count': retry_count,
        'canceled_count': canceled_count,
        'expired_count': expired_count,
        'finished_count': finished_count,
        'number_of_jobs': number_of_jobs,
        'cpucount_requested': cpucount_requested,
        'cpucount_done': cpucount_done,
        'nodecount_requested': nodecount_requested,
        'nodecount_done': nodecount_done,
        'cputime_requested': cputime_requested,
        'cputime_done': cputime_done,
        'used_walltime': used_walltime,
        'disk_requested': disk_requested,
        'disk_done': disk_done,
        'memory_requested': memory_requested,
        'memory_done': memory_done,
        'runtimeenv_requested': runtimeenv_requested,
        'runtimeenv_done': runtimeenv_done,
    }

    html += \
        """<h2>Job Stats</h2><table class=monitorstats><tr><td>
<table class=monitorjobs><tr class=title><td>Job State</td><td>Number of jobs</td></tr>
<tr><td>Parse</td><td>%(parse_count)s</td></tr>
<tr><td>Queued</td><td>%(queued_count)s</td></tr>
<tr><td>Frozen</td><td>%(frozen_count)s</td></tr>
<tr><td>Executing</td><td>%(executing_count)s</td></tr>
<tr><td>Failed</td><td>%(failed_count)s</td></tr>
<tr><td>Retry</td><td>%(retry_count)s</td></tr>
<tr><td>Canceled</td><td>%(canceled_count)s</td></tr>
<tr><td>Expired</td><td>%(expired_count)s</td></tr>
<tr><td>Finished</td><td>%(finished_count)s</td></tr>
<tr><td>Total</td><td>%(number_of_jobs)s</td></tr>
</table>
</td><td>
<table class=monitorresreq>
<tr class=title><td>Requirement</td><td>Requested</td><td>Done</td></tr>
<tr><td>Cpucount</td><td>%(cpucount_requested)s</td><td>%(cpucount_done)s</td></tr>
<tr><td>Nodecount</td><td>%(nodecount_requested)s</td><td>%(nodecount_done)s</td></tr>
<tr><td>Cputime</td><td>%(cputime_requested)s</td><td>%(cputime_done)s</td></tr>
<tr><td>GB Disk</td><td>%(disk_requested)s</td><td>%(disk_done)s</td></tr>
<tr><td>MB Memory</td><td>%(memory_requested)s</td><td>%(memory_done)s</td></tr>
<tr><td>Runtime Envs</td><td>%(runtimeenv_requested)s</td><td>%(runtimeenv_done)s</td></tr>
<tr><td>Used Walltime</td><td colspan='2'>%(used_walltime)s</td></tr>
</table><br />
</td><td>
<div class=monitorruntimeenvdetails>
<table class=monitorruntimeenvdone>
<tr class=title><td>Runtime Envs Done</td><td></td></tr>
"""\
         % html_vars

    if len(runtimeenv_dict.keys()) < 1:

        # No runtimeenv requests

        html += '<tr><td></td><td>-</td></tr>\n'
    else:
        for entry in runtimeenv_dict.keys():
            if not entry == '':
                html += '<tr><td>' + entry + '</td><td>'\
                    + str(runtimeenv_dict[entry]) + '</td></tr>\n'

    total_number_of_exe_resources, total_number_of_store_resources = 0, 0
    total_number_of_exe_cpus, total_number_of_store_gigs = 0, 0

    vgrid_name_list = vgrid_name.split('/')
    current_dir = ''

    exes, stores = '', ''
    for vgrid_name_part in vgrid_name_list:
        current_dir = os.path.join(current_dir, vgrid_name_part)
        abs_mon_dir = os.path.join(configuration.vgrid_home, current_dir)
        # print 'dir: %s' % abs_mon_dir
        # Potential race - just ignore if it disappeared
        try:
            sorted_names = os.listdir(abs_mon_dir)
        except OSError:
            continue
        sorted_names.sort()
        for filename in sorted_names:
            # print filename
            if filename.startswith('monitor_last_request_'):

                # read last request helper file

                mon_file_name = os.path.join(abs_mon_dir, filename)
                print 'found ' + mon_file_name
                last_request_dict = unpickle(mon_file_name, logger)
                if not last_request_dict:
                    print 'could not open and unpickle: '\
                        + mon_file_name
                    continue
                if not last_request_dict.has_key('CREATED_TIME'):
                    print 'skip broken last request dict: '\
                        + mon_file_name
                    continue

                difference = datetime.datetime.now()\
                    - last_request_dict['CREATED_TIME']
                days = str(difference.days)
                hours = str(difference.seconds / 3600)
                minutes = str((difference.seconds % 3600) / 60)
                seconds = str((difference.seconds % 60) % 60)

                last_timetuple = last_request_dict['CREATED_TIME'].timetuple()

                if last_request_dict.has_key('CPUTIME'):
                    cputime = last_request_dict['CPUTIME']
                elif last_request_dict.has_key('cputime'):
                    cputime = last_request_dict['cputime']
                else:
                    print 'ERROR: last request does not contain cputime field!: %s'\
                        % last_request_dict
                    continue

                try:
                    cpusec = int(cputime)
                except ValueError:
                    try:
                        cpusec = int(float(cputime))
                    except ValueError, verr:
                        print 'ERROR: failed to parse cputime %s: %s'\
                            % (cputime, verr)

                # Include execution delay guesstimate for strict fill
                # LRMS resources

                try:
                    delay = int(last_request_dict['EXECUTION_DELAY'])
                except KeyError:
                    delay = 0
                except ValueError:
                    delay = 0

                time_remaining = (last_request_dict['CREATED_TIME']
                                  + datetime.timedelta(seconds=cpusec)
                                  + datetime.timedelta(seconds=delay))\
                    - datetime.datetime.now()
                days_rem = str(time_remaining.days)
                hours_rem = str(time_remaining.seconds / 3600)
                minutes_rem = str((time_remaining.seconds % 3600) / 60)
                seconds_rem = str((time_remaining.seconds % 60) % 60)

                if time_remaining.days < -7:
                    try:
                        print 'removing: %s as we havent seen him for %s days.'\
                            % (mon_file_name, abs(time_remaining).days)
                        os.remove(mon_file_name)
                    except Exception, err:
                        print "could not remove: '%s' Error: %s"\
                            % (mon_file_name, str(err))
                    pass
                else:
                    unique_res_name_and_exe_list = \
                        filename.split('monitor_last_request_', 1)
                    if cpusec == 0:
                        resource_status = 'unavailable'
                    elif time_remaining.days < 0:

                        # time_remaining.days < 0 means that we have passed the specified time

                        time_rem_abs = abs(time_remaining)
                        if time_rem_abs.days == 0\
                                and int(time_rem_abs.seconds)\
                                < int(slackperiod):
                            resource_status = 'slack'
                            slack_count = slack_count + 1
                        else:
                            resource_status = 'offline'
                            down_count = down_count + 1
                    else:
                        resource_status = 'online'
                        up_count = up_count + 1

                    exes += '<tr>'
                    exes += \
                        '<td><img src=/images/status-icons/%s.png /></td>'\
                        % resource_status
                    public_id = unique_res_name_and_exe_list[1]
                    if last_request_dict['RESOURCE_CONFIG'].get(
                            'ANONYMOUS', True):
                        public_id = anon_resource_id(public_id)
                    public_name = last_request_dict['RESOURCE_CONFIG'].get(
                        'PUBLICNAME', '')
                    resource_parts = public_id.split('_', 2)
                    resource_name = "<a href='viewres.py?unique_resource_name=%s'>%s</a>" % \
                                    (resource_parts[0], resource_parts[0])
                    if public_name:
                        resource_name += "<br />(alias %s)" % public_name
                    else:
                        resource_name += "<br />(no alias)"
                    resource_name += "<br />%s" % resource_parts[1]
                    exes += '<td>%s</td>' % resource_name

                    last_asctime = time.asctime(last_timetuple)
                    last_epoch = time.mktime(last_timetuple)
                    exes += '<td><div class="sortkey">%s</div>%s<br />' %  \
                            (last_epoch, last_asctime)
                    exes += '(%sd %sh %sm %ss ago)</td>' % (days, hours,
                                                            minutes, seconds)
                    exes += '<td>' + vgrid_name + '</td>'
                    runtime_envs = last_request_dict['RESOURCE_CONFIG'][
                        'RUNTIMEENVIRONMENT']
                    runtime_envs.sort()
                    re_list_text = ', '.join([i[0] for i in runtime_envs])
                    exes += '<td title="%s">' % re_list_text \
                        + str(len(runtime_envs)) + '</td>'
                    exes += '<td>'\
                        + str(last_request_dict['RESOURCE_CONFIG'
                                                ]['CPUTIME']) + '</td><td>'\
                        + str(last_request_dict['RESOURCE_CONFIG'
                                                ]['NODECOUNT']) + '</td><td>'\
                        + str(last_request_dict['RESOURCE_CONFIG'
                                                ]['CPUCOUNT']) + '</td><td>'\
                        + str(last_request_dict['RESOURCE_CONFIG'
                                                ]['DISK']) + '</td><td>'\
                        + str(last_request_dict['RESOURCE_CONFIG'
                                                ]['MEMORY']) + '</td><td>'\
                        + str(last_request_dict['RESOURCE_CONFIG'
                                                ]['ARCHITECTURE']) + '</td>'
                    exes += '<td>' + last_request_dict['STATUS']\
                        + '</td><td>' + str(last_request_dict['CPUTIME'
                                                              ]) + '</td>'

                    exes += '<td class=status_%s>' % resource_status
                    if 'unavailable' == resource_status:
                        exes += '-'
                    elif 'slack' == resource_status:
                        exes += 'Within slack period (%s < %s secs)'\
                            % (time_rem_abs.seconds, slackperiod)
                    elif 'offline' == resource_status:
                        exes += 'down?'
                    else:
                        exes += '%sd, %sh, %sm, %ss'\
                            % (days_rem, hours_rem, minutes_rem,
                                seconds_rem)
                    exes += '</td>'

                    exes += '</tr>\n'
                    if last_request_dict['STATUS'] == 'Job assigned':
                        job_assigned = job_assigned + 1
                        job_assigned_cpus = job_assigned_cpus\
                            + int(last_request_dict['RESOURCE_CONFIG'
                                                    ]['NODECOUNT'])\
                            * int(last_request_dict['RESOURCE_CONFIG'
                                                    ]['CPUCOUNT'])

                    total_number_of_exe_resources += 1
                    total_number_of_exe_cpus += int(
                        last_request_dict['RESOURCE_CONFIG']['NODECOUNT']) \
                        * int(last_request_dict['RESOURCE_CONFIG']['CPUCOUNT'])
            elif filename.startswith('monitor_last_status_'):

                # store must be linked to this vgrid, not only parent vgrid:
                # inheritance only covers access, not automatic participation

                if current_dir != vgrid_name:
                    continue

                # read last resource action status file

                mon_file_name = os.path.join(abs_mon_dir, filename)
                print 'found ' + mon_file_name
                last_status_dict = unpickle(mon_file_name, logger)
                if not last_status_dict:
                    print 'could not open and unpickle: '\
                        + mon_file_name
                    continue
                if not last_status_dict.has_key('CREATED_TIME'):
                    print 'skip broken last request dict: '\
                        + mon_file_name
                    continue

                difference = datetime.datetime.now()\
                    - last_status_dict['CREATED_TIME']
                days = str(difference.days)
                hours = str(difference.seconds / 3600)
                minutes = str((difference.seconds % 3600) / 60)
                seconds = str((difference.seconds % 60) % 60)

                if last_status_dict['STATUS'] == 'stopped':
                    time_stopped = datetime.datetime.now() - \
                        last_status_dict['CREATED_TIME']
                    if time_stopped.days > 7:
                        try:
                            print 'removing: %s as we havent seen him for %s days.'\
                                  % (mon_file_name, abs(time_stopped).days)
                            os.remove(mon_file_name)
                        except Exception, err:
                            print "could not remove: '%s' Error: %s"\
                                  % (mon_file_name, str(err))
                        continue
コード例 #6
0
ファイル: resadmin.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = initialize_main_variables(client_id, op_header=False)
    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)
コード例 #7
0
ファイル: vgridworkflows.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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)
コード例 #8
0
def initialize_main_variables(client_id,
                              op_title=True,
                              op_header=True,
                              op_menu=True):
    """Script initialization is identical for most scripts in 
    shared/functionalty. This function should be called in most cases.
    """

    configuration = get_configuration_object()
    logger = configuration.logger
    output_objects = []
    start_entry = make_start_entry()
    output_objects.append(start_entry)
    op_name = os.path.splitext(os.path.basename(requested_page()))[0]

    if op_title:
        skipwidgets = not configuration.site_enable_widgets or not client_id
        skipuserstyle = not configuration.site_enable_styling or not client_id
        title_object = make_title_entry('%s' % op_name,
                                        skipmenu=(not op_menu),
                                        skipwidgets=skipwidgets,
                                        skipuserstyle=skipuserstyle,
                                        skipuserprofile=(not client_id))
        # Make sure base_menu is always set for extract_menu
        # Typicall overriden based on client_id cases below
        title_object['base_menu'] = configuration.site_default_menu
        output_objects.append(title_object)
    if op_header:
        header_object = make_header_entry('%s' % op_name)
        output_objects.append(header_object)
    if client_id:
        # add the user-defined menu and widgets (if possible)
        title = find_entry(output_objects, 'title')
        if title:
            settings = load_settings(client_id, configuration)
            # NOTE: loaded settings may be False rather than dict here
            if not settings:
                settings = {}
            title['style'] = themed_styles(configuration,
                                           user_settings=settings)
            title['script'] = themed_scripts(configuration,
                                             user_settings=settings)
            if settings:
                title['user_settings'] = settings
                base_menu = settings.get('SITE_BASE_MENU', 'default')
                if not base_menu in configuration.site_base_menu:
                    base_menu = 'default'
                if base_menu == 'simple' and configuration.site_simple_menu:
                    title['base_menu'] = configuration.site_simple_menu
                elif base_menu == 'advanced' and \
                        configuration.site_advanced_menu:
                    title['base_menu'] = configuration.site_advanced_menu
                else:
                    title['base_menu'] = configuration.site_default_menu
                user_menu = settings.get('SITE_USER_MENU', None)
                if configuration.site_user_menu and user_menu:
                    title['user_menu'] = user_menu
                if settings.get('ENABLE_WIDGETS', True) and \
                        configuration.site_script_deps:
                    user_widgets = load_widgets(client_id, configuration)
                    if user_widgets:
                        title['user_widgets'] = user_widgets
            user_profile = load_profile(client_id, configuration)
            if user_profile:
                # These data are used for display in own profile view only
                profile_image_list = user_profile.get('PUBLIC_IMAGE', [])
                if profile_image_list:
                    # TODO: copy profile image to /public/avatars/X and use it
                    profile_image = os.path.join(
                        configuration.site_user_redirect,
                        profile_image_list[-1])
                else:
                    profile_image = ''
                user_profile['profile_image'] = profile_image
            else:
                user_profile = {}
            # Always set full name for use in personal user menu
            full_name = extract_field(client_id, 'full_name')
            user_profile['full_name'] = full_name
            title['user_profile'] = user_profile
            logger.debug('setting user profile: %s' % user_profile)
    else:
        # No user so we just enforce default site style and scripts
        title = find_entry(output_objects, 'title')
        if title:
            title['style'] = themed_styles(configuration)
            title['script'] = themed_scripts(configuration, logged_in=False)
    return (configuration, logger, output_objects, op_name)
コード例 #9
0
ファイル: resman.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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)
コード例 #10
0
ファイル: vmachines.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    output_objects.append({'object_type': 'header', 'text':
                           'Virtual Machines'})
    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)

    machine_name = accepted['machine_name'][-1].strip()
    memory = int(accepted['memory'][-1])
    disk = int(accepted['disk'][-1])
    vgrid = [name.strip() for name in accepted['vgrid']]
    architecture = accepted['architecture'][-1].strip()
    cpu_count = int(accepted['cpu_count'][-1])
    cpu_time = int(accepted['cpu_time'][-1])
    op_sys = accepted['os'][-1].strip()
    flavor = accepted['flavor'][-1].strip()
    hypervisor_re = accepted['hypervisor_re'][-1].strip()
    sys_re = accepted['sys_re'][-1].strip()
    action = accepted['action'][-1].strip()

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

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

    css_helpers = {'css_base': os.path.join(configuration.site_images, 'css'),
                   'skin_base': configuration.site_skin_base}
    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" >

$(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"); }
                }
              });

          $(".vm-tabs").tabs();
     }
);
</script>
'''

    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)

    machine_req = {'memory': memory, 'disk': disk, 'cpu_count': cpu_count,
                   'cpu_time': cpu_time, 'architecture': architecture,
                   'vgrid': vgrid, 'os': op_sys, 'flavor': flavor,
                   'hypervisor_re': hypervisor_re, 'sys_re': sys_re}
    
    menu_items = ['vmrequest']

    # Html fragments

    submenu = render_menu(configuration, menu_class='navsubmenu',
                          base_menu=[], user_menu=menu_items)

    welcome_text = 'Welcome to your %s virtual machine management!' % \
                   configuration.short_title
    desc_text = '''On this page you can:
<ul>
    <li>Request Virtual Machines, by clicking on the button above</li>
    <li>See your virtual machines in the list below.</li>
    <li>Start, and connect to your Virtual Machine by clicking on it.</li>
    <li>Edit or delete your Virtual Machine from the Advanced tab.</li>
</ul>
'''

    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': 'html_form', 'text': submenu})
    output_objects.append({'object_type': 'html_form', 'text'
                          : '<p>&nbsp;</p>'})
    output_objects.append({'object_type': 'sectionheader', 'text'
                          : welcome_text})
    output_objects.append({'object_type': 'html_form', 'text'
                          : desc_text})


    user_vms = vms.vms_list(client_id, configuration)
    if action == 'create':
        if not configuration.site_enable_vmachines:
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 "Virtual machines are disabled on this server"})
            status = returnvalues.CLIENT_ERROR
            return (output_objects, status)
        if not machine_name:
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 "requested build without machine name"})
            status = returnvalues.CLIENT_ERROR
            return (output_objects, status)            
        elif machine_name in [vm["name"] for vm in user_vms]:
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 "requested machine name '%s' already exists!" % machine_name})
            status = returnvalues.CLIENT_ERROR
            return (output_objects, status)
        elif not flavor in vms.available_flavor_list(configuration):
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 "requested pre-built flavor not available: %s" % flavor})
            status = returnvalues.CLIENT_ERROR
            return (output_objects, status)
        elif not hypervisor_re in \
                 vms.available_hypervisor_re_list(configuration):
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 "requested hypervisor runtime env not available: %s" % \
                 hypervisor_re})
        elif not sys_re in vms.available_sys_re_list(configuration):
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 "requested system pack runtime env not available: %s" % \
                 sys_re})
            status = returnvalues.CLIENT_ERROR
            return (output_objects, status)

        # TODO: support custom build of machine using shared/vmbuilder.py

        # request for existing pre-built machine

        vms.create_vm(client_id, configuration, machine_name, machine_req)

    (action_status, action_msg, job_id) = (True, '', None)
    if action in ['start', 'stop', 'edit', 'delete']:
        if not configuration.site_enable_vmachines:
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 "Virtual machines are disabled on this server"})
            status = returnvalues.CLIENT_ERROR
            return (output_objects, status)
    if action == 'start':
        machine = {}
        for entry in user_vms:
            if machine_name == entry['name']:
                for name in machine_req.keys():
                    if isinstance(entry[name], basestring) and \
                                  entry[name].isdigit():
                        machine[name] = int(entry[name])
                    else:
                        machine[name] = entry[name]
                break
        (action_status, action_msg, job_id) = \
                        vms.enqueue_vm(client_id, configuration, machine_name,
                                       machine)
    elif action == 'edit':
        if not machine_name in [vm['name'] for vm in user_vms]:
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 "No such virtual machine: %s" % machine_name})
            status = returnvalues.CLIENT_ERROR
            return (output_objects, status)
        (action_status, action_msg) = \
                        vms.edit_vm(client_id, configuration, machine_name,
                                    machine_req)
    elif action == 'delete':
        if not machine_name in [vm['name'] for vm in user_vms]:
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 "No such virtual machine: %s" % machine_name})
            status = returnvalues.CLIENT_ERROR
            return (output_objects, status)
        (action_status, action_msg) = \
                        vms.delete_vm(client_id, configuration, machine_name)
    elif action == 'stop':
        
        # TODO: manage stop - use live I/O to create vmname.stop in job dir

        pass

    if not action_status:
        output_objects.append({'object_type': 'error_text', 'text':
                               action_msg})
    
    # List the machines here

    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Your machines:'})

    # Grab the vms available for the user

    machines = vms.vms_list(client_id, configuration)

    # Visual representation mapping of the machine state

    machine_states = {
        'EXECUTING': 'vm_running.jpg',
        'CANCELED': 'vm_off.jpg',
        'FAILED': 'vm_off.jpg',
        'FINISHED': 'vm_off.jpg',
        'UNKNOWN': 'vm_off.jpg',
        'QUEUED': 'vm_booting.jpg',
        'PARSE': 'vm_booting.jpg',
        }

    # Empirical upper bound on boot time in seconds used to decide between
    # desktop init and ready states

    boot_secs = 130

    # CANCELED/FAILED/FINISHED -> Powered Off
    # QUEUED -> Booting

    if len(machines) > 0:

        # Create a pretty list with start/edit/stop/connect links

        pretty_machines = \
            '<table style="border: 0; background: none;"><tr>'
        side_by_side = 3  # How many machines should be shown in a row?

        col = 0
        for machine in machines:

            # Machines on a row

            if col % side_by_side == 0:
                pretty_machines += '</tr><tr>'
            col += 1

            # Html format machine specifications in a fieldset

            password = '******'
            exec_time = 0
            if machine['job_id'] != 'UNKNOWN' and \
                   machine['status'] == 'EXECUTING':

                # TODO: improve on this time selection...
                # ... in distributed there is no global clock!

                exec_time = time.time() - 3600 \
                            - time.mktime(machine['execution_time'])
                password = vms.vnc_jobid(machine['job_id'])

            machine_specs = {}
            machine_specs.update(machine)
            machine_specs['password'] = password
            show_specs = """<fieldset>
<legend>VM Specs:</legend><ul class="no-bullets">
<li><input type="text" readonly value="%(os)s"> base system</li>
<li><input type="text" readonly value="%(flavor)s"> software flavor</li>
<li><input type="text" readonly value="%(memory)s"> MB memory</li>
<li><input type="text" readonly value="%(disk)s"> GB disk</li>
<li><input type="text" readonly value="%(cpu_count)s"> CPU's</li>
<li><input type="text" readonly value="%(vm_arch)s"> architecture</li>
"""
            if password != 'UNKNOWN':
                show_specs += """            
<li><input type="text" readonly value="%(password)s"> as VNC password</li>
"""
            show_specs += """            
</form></ul></fieldset>"""
            edit_specs = """<fieldset>
<legend>Edit VM Specs:</legend><ul class="no-bullets">
<form method="post" action="vmachines.py">
<input type="hidden" name="action" value="edit">
<input type="hidden" name="machine_name" value="%(name)s">
<input type="hidden" name="output_format" value="html">

<li><input type="text" readonly name="os" value="%(os)s"> base system</li>
<li><input type="text" readonly name="flavor" value="%(flavor)s"> software flavor</li>
<li><input type="text" readonly name="hypervisor_re" value="%(hypervisor_re)s"> hypervisor runtime env</li>
<li><input type="text" readonly name="sys_re" value="%(sys_re)s"> image pack runtime env</li>
<li><input type="text" name="memory" value="%(memory)s"> MB memory</li>
<li><input type="text" name="disk" value="%(disk)s"> GB disk</li>
<li><input type="text" name="cpu_count" value="%(cpu_count)s"> CPU's</li>
<li><select name="architecture">
"""
            for arch in [''] + configuration.architectures:
                select = ''
                if arch == machine_specs['architecture']:
                    select = 'selected'
                edit_specs += "<option %s value='%s'>%s</option>" % (select, arch,
                                                                arch)
            edit_specs += """</select> resource architecture
<li><input type="text" name="cpu_time" value="%(cpu_time)s"> s time slot</li>
<li><select name="vgrid" multiple>"""
            for vgrid_name in [any_vgrid] + \
                    user_allowed_vgrids(configuration, client_id):
                select = ''
                if vgrid_name in machine_specs['vgrid']:
                    select = 'selected'
                edit_specs += "<option %s>%s</option>" % (select, vgrid_name)
            edit_specs += """</select> %s(s)</li>""" % \
                          configuration.site_vgrid_label
            if password != 'UNKNOWN':
                edit_specs += """
<li><input type="text" readonly value="%(password)s"> as VNC password</li>
"""
            edit_specs += """
<input class="styled_button" type="submit" value="Save Changes">
</form>"""
            js_name = 'deletevm%s' % hexlify("%(name)s" % machine_specs)
            helper = html_post_helper(js_name, 'vmachines.py',
                                      {'machine_name': machine_specs['name'],
                                       'action': 'delete'})
            edit_specs += helper
            edit_specs += """<input class="styled_button" type="submit"
value="Delete Machine" onClick="javascript: confirmDialog(%s, '%s');" >
""" % (js_name, "Really permanently delete %(name)s VM?" % machine_specs)
            edit_specs += """</ul></fieldset>"""
            if machine['status'] == 'EXECUTING' and exec_time > boot_secs:
                machine_image = '<img src="/images/vms/' \
                    + machine_states[machine['status']] + '">'
            elif machine['status'] == 'EXECUTING' and exec_time < boot_secs:
                machine_image = \
                    '<img src="/images/vms/vm_desktop_loading.jpg' \
                    + '">'
            else:
                machine_image = '<img src="/images/vms/' \
                    + machine_states[machine['status']] + '">'
            machine_link = vms.machine_link(machine_image,
                    machine['job_id'], machine['name'], machine['uuid'
                    ], machine['status'], machine_req)

            # Smack all the html together

            fill_dict = {}
            fill_dict.update(machine)
            fill_dict['link'] = machine_link
            fill_dict['show_specs'] = show_specs % machine_specs
            fill_dict['edit_specs'] = edit_specs % machine_specs
            pretty_machines += '''
<td style="vertical-align: top;">
<fieldset><legend>%(name)s</legend>
<div id="%(name)s-tabs" class="vm-tabs">
<ul>
<li><a href="#%(name)s-overview">Overview</a></li>
<li><a href="#%(name)s-edit">Advanced</a></li>
</ul>
<div id="%(name)s-overview">
<p>%(link)s</p>
%(show_specs)s
</div>
<div id="%(name)s-edit">
%(edit_specs)s
</div>
</div>
</fieldset>
</td>''' % fill_dict

        pretty_machines += '</tr></table>'

        output_objects.append({'object_type': 'html_form', 'text'
                              : pretty_machines})
    else:
        output_objects.append(
            {'object_type': 'text', 'text'
             : "You don't have any virtual machines! "
             "Click 'Request Virtual Machine' to become a proud owner :)"
             })

    return (output_objects, status)
コード例 #11
0
ファイル: freezedb.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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'] = 'Frozen Archives'

    # 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. 0 (ID)
          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;
          }

          $("#frozenarchivetable").tablesorter({widgets: ["zebra", "saveSort"],
                                        sortList:sortOrder,
                                        textExtraction: imgTitle
                                        })
                               .tablesorterPager({ container: $("#pager"),
                                        size: %s
                                        });
     }
);
</script>
''' % default_pager_entries

    output_objects.append({'object_type': 'header', 'text'
                          : 'Frozen Archives'})
    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>
'''                       })

    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)

    output_objects.append(
        {'object_type': 'text', 'text' :
         '''Frozen archives are write-once collections of files used e.g. in
 relation to conference paper submissions. Please note that local policies may
 prevent users from deleting frozen archives without explicit acceptance from
 the management.
         '''})

    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Existing frozen archives'})

    (status, ret) = list_frozen_archives(configuration, client_id)
    if not 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)

    frozenarchives = []
    for freeze_id in ret:
        (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 details for "%s"' % \
                                   freeze_id})
            return (output_objects, returnvalues.SYSTEM_ERROR)
        freeze_item = build_freezeitem_object(configuration, freeze_dict)
        freeze_id = freeze_item['id']
        flavor = freeze_item.get('flavor', 'freeze')
        
        freeze_item['viewfreezelink'] = {
            'object_type': 'link',
            'destination': "showfreeze.py?freeze_id=%s;flavor=%s" % \
            (freeze_id, flavor),
            'class': 'infolink', 
            'title': 'View frozen archive %s' % freeze_id, 
            'text': ''}
        if client_id == freeze_item['creator']:
            js_name = 'delete%s' % hexlify(freeze_id)
            helper = html_post_helper(js_name, 'deletefreeze.py',
                                      {'freeze_id': freeze_id,
                                       'flavor': flavor})
            output_objects.append({'object_type': 'html_form', 'text': helper})
            freeze_item['delfreezelink'] = {
                'object_type': 'link', 'destination':
                "javascript: confirmDialog(%s, '%s');" % \
                (js_name, 'Really remove %s?' % freeze_id),
                'class': 'removelink', 'title': 'Remove %s' % \
                freeze_id, 'text': ''}
        frozenarchives.append(freeze_item)

    output_objects.append({'object_type': 'table_pager', 'entry_name':
                           'frozen archives',
                           'default_entries': default_pager_entries})
    output_objects.append({'object_type': 'frozenarchives',
                          'frozenarchives': frozenarchives})

    output_objects.append({'object_type': 'sectionheader', 'text':
                           'Additional Frozen Archives'})
    output_objects.append({'object_type': 'link',
                           'destination': 'adminfreeze.py',
                           'class': 'addlink',
                           'title': 'Specify a new frozen archive', 
                           'text': 'Create a new frozen archive'})

    return (output_objects, returnvalues.OK)
コード例 #12
0
ファイル: vgridadmin.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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)

    (stat, vgrid_list) = vgrid_list_vgrids(configuration)
    if not stat:
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'Error getting list of %s.' % \
                               configuration.site_vgrid_label})

    # Check if user wants advanced VGrid component links

    settings = load_settings(client_id, configuration)        
    collaboration_links = 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

    # Iterate through vgrids and print details for each

    member_list = {'object_type': 'vgrid_list', 'vgrids': [],
                   'components': active_vgrid_links}
    if 'monitor' in active_vgrid_links:
        vgrid_list = [all_vgrids] + vgrid_list
    else:
        vgrid_list.remove(default_vgrid)
    for vgrid_name in vgrid_list:
        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',
                                               'title': 'View %s monitor' % vgrid_name, 
                                               'text': 'View'}
            vgrid_obj['memberlink'] = {'object_type': 'link',
                                       'destination':'',
                                       'class': 'infolink',
                                       'title': 'Every user is member of the %s %s' \
                                       % (default_vgrid,
                                          configuration.site_vgrid_label),
                                       'text': ''}
            vgrid_obj['administratelink'] = {'object_type': 'link',
                                       'destination':'',
                                       'class': 'infolink',
                                       'title': 'Nobody owns the %s %s' \
                                       % (default_vgrid,
                                          configuration.site_vgrid_label),
                                       'text': ''}
            member_list['vgrids'].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',
                                               'title': 'View global monitor', 
                                               'text': 'View'}
            vgrid_obj['memberlink'] = {'object_type': 'link',
                                       'destination':'',
                                       'class': 'infolink',
                                       'title': 'Not a real %s - only for global monitor' % \
                                       configuration.site_vgrid_label,
                                       'text': ''}
            vgrid_obj['administratelink'] = {'object_type': 'link',
                                       'destination':'',
                                       'class': 'infolink',
                                       'title': 'Not a real %s - only for global monitor' % \
                                             configuration.site_vgrid_label,
                                       'text': ''}
            member_list['vgrids'].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',
                                       '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',
                                       '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',
                                        'title': 'View public %s web page' % \
                                        vgrid_name,
                                        'text': 'View'}

        # link to become member: overwritten later for members

        js_name = 'reqvgridmember%s' % hexlify(vgrid_name)
        helper = html_post_helper(js_name, 'sendrequestaction.py',
                                  {'vgrid_name': vgrid_name,
                                   'request_type': 'vgridmember',
                                   'request_text': ''})
        output_objects.append({'object_type': 'html_form', 'text': helper})
        vgrid_obj['memberlink'] = \
                                {'object_type': 'link',
                                 'destination':
                                 "javascript: confirmDialog(%s, '%s', '%s');"\
                                 % (js_name, "Request membership of " + \
                                    vgrid_name + ":<br/>" + \
                                    "\nPlease write a message to the owners (field below).",
                                    'request_text'),
                                 'class': 'addlink',
                                 'title': 'Request membership of %s' % \
                                 vgrid_name,
                                 'text': ''}

        # link to become owner: overwritten later for owners

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

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

        if vgrid_is_owner_or_member(vgrid_name, client_id, configuration):
            vgrid_obj['enterprivatelink'] = {'object_type': 'link',
                                             'destination':
                                             '../vgrid/%s/path/index.html' % \
                                             vgrid_name,
                                             'class': 'urllink owner',
                                             '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',
                                             'title': 'Open shared %s folder' \
                                             % vgrid_name, 
                                             'text': 'Open'}
            vgrid_obj['memberscmlink'] = {'object_type': 'link',
                                          'destination': '/vgridscm/%s' % \
                                          vgrid_name,
                                          'class': 'scmlink member',
                                          'title': 'View %s members scm' % \
                                          vgrid_name,
                                          'text': 'View'}
            vgrid_obj['membertrackerlink'] = {'object_type': 'link',
                                          'destination': '/vgridtracker/%s' % \
                                          vgrid_name,
                                          'class': 'trackerlink member',
                                          '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',
                                             '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',
                                             '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',
                                               '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.

            js_name = 'rmvgridmember%s' % hexlify(vgrid_name)
            helper = html_post_helper(js_name, 'rmvgridmember.py',
                                      {'vgrid_name': vgrid_name,
                                       'cert_id': client_id})
            output_objects.append({'object_type': 'html_form', 'text': helper})
            vgrid_obj['memberlink'] = \
                                    {'object_type': 'link',
                                     'destination':
                                     "javascript: confirmDialog(%s, '%s');"\
                                     % (js_name, "Really leave " + vgrid_name + "?"),
                                     'class': 'removelink',
                                     'title': 'Leave %s members' % vgrid_name, 
                                     'text': ''}
            
        # owners are allowed to edit pages and administrate

        if vgrid_is_owner(vgrid_name, client_id, configuration):
            vgrid_obj['ownerscmlink'] = {'object_type': 'link',
                                         'destination': '/vgridownerscm/%s' % \
                                         vgrid_name,
                                         'class': 'scmlink owner',
                                         'title': 'View %s owners scm' % \
                                         vgrid_name,
                                         'text': 'View'}
            vgrid_obj['ownertrackerlink'] = {'object_type': 'link',
                                         'destination': '/vgridownertracker/%s' % \
                                         vgrid_name,
                                         'class': 'trackerlink owner',
                                         'title': 'View %s owners tracker' % \
                                         vgrid_name,
                                         'text': 'View'}

            # correct the link to leave the VGrid

            js_name = 'rmvgridowner%s' % hexlify(vgrid_name)
            helper = html_post_helper(js_name, 'rmvgridowner.py',
                                      {'vgrid_name': vgrid_name,
                                       'cert_id': client_id})
            output_objects.append({'object_type': 'html_form', 'text': helper})
            vgrid_obj['memberlink']['destination'] = \
                      "javascript: confirmDialog(%s,'%s');" % \
                      (js_name, "Really leave " + vgrid_name + "?")
            vgrid_obj['memberlink']['class'] = 'removeadminlink'
            vgrid_obj['memberlink']['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',
                                             'title': 'Administrate %s' % vgrid_name,
                                             'text': ''}
            vgrid_obj['editprivatelink'] = {'object_type': 'link',
                                            'destination': 'fileman.py?path=private_base/%s/'\
                                            % vgrid_name,
                                            'class': 'editlink owner',
                                            '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',
                                           'title': 'Edit public %s web page' % vgrid_name,
                                           'text': 'Edit'}


        member_list['vgrids'].append(vgrid_obj)

    title_entry = find_entry(output_objects, 'title')
    label = "%ss" % configuration.site_vgrid_label
    # Append VGrid note if custom
    if label != 'VGrid':
        label += ' (i.e. VGrids)'
    title_entry['text'] = '%s administration' % label

    # 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 2 (member), then 0 (name)
          var sortOrder = [[1,1],[2,1],[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;
          }

          $("#vgridtable").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': 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.
''' % configuration.site_vgrid_label
                       })

    if configuration.site_vgrid_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.""" % \
                               configuration.site_vgrid_label})

    output_objects.append({'object_type': 'sectionheader', 'text'
                          : '%ss managed on this server' % \
                           configuration.site_vgrid_label})
    output_objects.append({'object_type': 'table_pager', 'entry_name': '%ss' % \
                           configuration.site_vgrid_label,
                           'default_entries': default_pager_entries})
    output_objects.append(member_list)

    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' % \
                               configuration.site_vgrid_label})

        output_objects.append(
            {'object_type': 'text', 'text':
             '''Please enter a name for the new %(label)s to add, using slashes to
 specify nesting. I.e. if you own a %(label)s called ABC, you can create a
 sub-%(label)s called DEF by entering ABC/DEF below.''' % \
             {'label': configuration.site_vgrid_label}})
        output_objects.append({'object_type': 'html_form', 'text':
                                '''<form method="post" action="createvgrid.py">
    <input type="text" size=40 name="vgrid_name" />
    <input type="hidden" name="output_format" value="html" />
    <input type="submit" value="Create %s" />
    </form>
 ''' % configuration.site_vgrid_label})

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

    output_objects.append(
        {'object_type': 'text', 'text':
         '''You can request access to %(label)ss using the individual plus-icons above directly or by entering the name of the %(label)s to request access to, what kind of access and an optional message to the admins below''' % \
             {'label': configuration.site_vgrid_label}})
    output_objects.append({'object_type': 'html_form', 'text':
                           '''<form method="post" action="sendrequestaction.py">
    <input type="text" size=40 name="vgrid_name" />
    <select name="request_type">
        <option value="vgridmember">membership</option> 
        <option value="vgridowner">ownership</option>
    </select>
    <input type="text" size=50 name="request_text" />
    <input type="hidden" name="output_format" value="html" />
    <input type="submit" value="Request %s access" />
    </form>
 ''' % configuration.site_vgrid_label})

    return (output_objects, status)
コード例 #13
0
ファイル: submitjob.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

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

    show_description = accepted['description'][-1].lower() == 'true'

    # 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

    template_path = os.path.join(base_dir, default_mrsl_filename)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Submit Job'
    output_objects.append({'object_type': 'header', 'text'
                          : 'Submit Job'})
    default_mrsl = get_default_mrsl(template_path)
    settings_dict = load_settings(client_id, configuration)
    if not settings_dict or not settings_dict.has_key('SUBMITUI'):
        logger.info('Settings dict does not have SUBMITUI key - using default'
                    )
        submit_style = configuration.submitui[0]
    else:
        submit_style = settings_dict['SUBMITUI']

    # We generate all 3 variants of job submission (fields, textarea, files),
    # initially hide them and allow to switch between them using js.

    # could instead extract valid prefixes as in settings.py
    # (means: by "eval" from configuration). We stick to hard-coding.
    submit_options = ['fields_form', 'textarea_form', 'files_form']

    css_helpers = {'css_base': os.path.join(configuration.site_images, 'css'),
                   'skin_base': configuration.site_skin_base}
    title_entry['style'] = themed_styles(configuration,
                                         base=['jquery.fileupload.css',
                                               'jquery.fileupload-ui.css'],
                                         skin=['fileupload-ui.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 is only needed for fancy upload init wrapper -->
<script type="text/javascript" src="/images/js/jquery.form.js"></script>
<script type="text/javascript" src="/images/js/jquery.filemanager.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>
<!-- 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>

<script type="text/javascript" >

    options = %s;

    function setDisplay(this_id, new_d) {
        //console.log("setDisplay with: "+this_id);
        el = document.getElementById(this_id)
        if ( el == undefined || el.style == undefined ) {
            console.log("failed to locate display element: "+this_id);
            return; // avoid js null ref errors
        }
        el.style.display=new_d;
    }

    function switchTo(name) {
        //console.log("switchTo: "+name);
        for (o=0; o < options.length; o++) {
            if (name == options[o]) {
                setDisplay(options[o],"block");
            } else {
                setDisplay(options[o],"none");
            }
        }
    }

    function openFancyUpload() {
        var open_dialog = mig_fancyuploadchunked_init("fancyuploadchunked_dialog");
        var remote_path = ".";
        open_dialog("Upload Files", function() { return false; },
                    remote_path, false);
    }

    $(document).ready( function() {
         //console.log("document ready handler");
         switchTo("%s");
         $("#fancydialog").click(openFancyUpload);
    });

</script>
''' % (submit_options, submit_style + "_form")

    output_objects.append({'object_type': 'text', 'text':
                           'This page is used to submit jobs to the grid.'})

    output_objects.append({'object_type': 'verbatim',
                           'text': '''
There are %s interface styles available that you can choose among:''' % \
                           len(submit_options)})

    links = []
    for opt in submit_options:
        name = opt.split('_', 2)[0] 
        links.append({'object_type': 'link', 
                      'destination': "javascript:switchTo('%s')" % opt,
                      'class': 'submit%slink' % name,
                      'title': 'Switch to %s submit interface' % name,
                      'text' : '%s style' % name,
                      })
    output_objects.append({'object_type': 'multilinkline', 'links': links})

    output_objects.append({'object_type': 'text', 'text': '''
Please note that changes to the job description are *not* automatically
transferred if you switch style.'''}) 

    output_objects.append({'object_type': 'html_form', 'text':
                           '<div id="fields_form" style="display:none;">\n'})
    
    # Fields
    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Please fill in your job description in the fields'
                           ' below:'
                          })
    output_objects.append({'object_type': 'text', 'text'
                          : """
Please fill in one or more fields below to define your job before hitting
Submit Job at the bottom of the page.
Empty fields will simply result in the default value being used and each field
is accompanied by a help link providing further details about the field."""})
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<div class="submitjob">
<form method="post" action="submitfields.py">
"""
                          })
    show_fields = get_job_specs(configuration)
    try:
        parsed_mrsl = dict(parse_lines(default_mrsl))
    except:
        parsed_mrsl = {}

    # Find allowed VGrids and Runtimeenvironments and add them to
    # configuration object for automated choice handling
    
    allowed_vgrids = user_allowed_vgrids(configuration, client_id) + \
                     [any_vgrid]
    allowed_vgrids.sort()
    configuration.vgrids = allowed_vgrids
    (re_status, allowed_run_envs) = list_runtime_environments(configuration)
    if not re_status:
        logger.error('Failed to extract allowed runtime envs: %s' % \
                     allowed_run_envs)
        allowed_run_envs = []
    allowed_run_envs.sort()
    configuration.runtimeenvironments = allowed_run_envs
    user_res = user_allowed_res_exes(configuration, client_id)

    # Allow any exe unit on all allowed resources
        
    allowed_resources = ['%s_*' % res for res in user_res.keys()]
    allowed_resources.sort()
    configuration.resources = allowed_resources
    field_size = 30
    area_cols = 80
    area_rows = 5

    for (field, spec) in show_fields:
        title = spec['Title']
        if show_description:
            description = '%s<br />' % spec['Description']
        else:
            description = ''
        field_type = spec['Type']
        # Use saved value and fall back to default if it is missing
        saved = parsed_mrsl.get('::%s::' % field, None)
        if saved:
            if not spec['Type'].startswith('multiple'):
                default = saved[0]
            else:
                default = saved
        else:
            default = spec['Value']
        # Hide sandbox field if sandboxes are disabled
        if field == 'SANDBOX' and not configuration.site_enable_sandboxes:
            continue
        if 'invisible' == spec['Editor']:
            continue
        if 'custom' == spec['Editor']:
            continue
        output_objects.append({'object_type': 'html_form', 'text'
                                   : """
<b>%s:</b>&nbsp;<a class='infolink' href='docs.py?show=job#%s'>help</a><br />
%s""" % (title, field, description)
                               })
        
        if 'input' == spec['Editor']:
            if field_type.startswith('multiple'):
                output_objects.append({'object_type': 'html_form', 'text'
                                       : """
<textarea name='%s' cols='%d' rows='%d'>%s</textarea><br />
""" % (field, area_cols, area_rows, '\n'.join(default))
                               })
            else:
                output_objects.append({'object_type': 'html_form', 'text'
                                       : """
<input type='text' name='%s' size='%d' value='%s' /><br />
""" % (field, field_size, default)
                               })
        elif 'select' == spec['Editor']:
            choices = available_choices(configuration, client_id,
                                        field, spec)
            res_value = default
            value_select = ''
            if field_type.startswith('multiple'):
                value_select += '<div class="scrollselect">'
                for name in choices:
                    # Blank default value does not make sense here
                    if not str(name):
                        continue
                    selected = ''
                    if str(name) in res_value:
                        selected = 'checked'
                    value_select += '''
                        <input type="checkbox" name="%s" %s value=%s>%s<br />
                        ''' % (field, selected, name, name)
                value_select += '</div>\n'
            else:
                value_select += "<select name='%s'>\n" % field
                for name in choices:
                    selected = ''
                    if str(res_value) == str(name):
                        selected = 'selected'
                    display = "%s" % name
                    if display == '':
                        display = ' '
                    value_select += """<option %s value='%s'>%s</option>\n""" \
                                    % (selected, name, display)
                value_select += """</select><br />\n"""    
            output_objects.append({'object_type': 'html_form', 'text'
                                   : value_select
                                   })
        output_objects.append({'object_type': 'html_form', 'text': "<br />"})

    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<br />
<table class='centertext'>
<tr><td><input type='submit' value='Submit Job' />
<input type='checkbox' name='save_as_default'> Save as default job template
</td></tr>
</table>
<br />
</form>
</div>
"""
                           })
    output_objects.append({'object_type': 'html_form', 
                           'text': '''
</div><!-- fields_form-->
<div id="textarea_form" style="display:none;">
'''})
    
    # Textarea
    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Please enter your mRSL job description below:'
                          })
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<div class='smallcontent'>
Job descriptions can use a wide range of keywords to specify job requirements
and actions.<br />
Each keyword accepts one or more values of a particular type.<br />
The full list of keywords with their default values and format is available in
the on-demand <a href='docs.py?show=job'>mRSL Documentation</a>.
<p>
Actual examples for inspiration:
<a href=/public/cpuinfo.mRSL>CPU Info</a>,
<a href=/public/basic-io.mRSL>Basic I/O</a>,
<a href=/public/notification.mRSL>Job Notification</a>,
<a href=/public/povray.mRSL>Povray</a> and
<a href=/public/vcr.mRSL>VCR</a>
</div>
    """})

    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<!-- 
Please note that textarea.py chokes if no nonempty KEYWORD_X_Y_Z fields 
are supplied: thus we simply send a bogus jobname which does nothing
-->
<form method="post" action="textarea.py">
<table class="submitjob">
<tr><td class="centertext">
<input type=hidden name=jobname_0_0_0 value=" " />
<textarea cols="82" rows="25" name="mrsltextarea_0">
%(default_mrsl)s
</textarea>
</td></tr>
<tr><td class='centertext'>
<input type="submit" value="Submit Job" />
<input type="checkbox" name="save_as_default" >Save as default job template
</td></tr>
</table>
</form>
"""
                           % {'default_mrsl': default_mrsl}})

    output_objects.append({'object_type': 'html_form', 
                           'text': '''
</div><!-- textarea_form-->
<div id="files_form" style="display:none;">
'''})
    # Upload form

    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Please upload your job file or packaged job files'
                           ' below:'
                          })
    output_objects.append({'object_type': 'html_form', 'text'
                          : """
<form enctype='multipart/form-data' action='textarea.py' method='post'>
<table class='files'>
<tr class='title'><td class='centertext' colspan=4>
Upload job files
</td></tr>
<tr><td colspan=3>
Upload file to current directory (%(dest_dir)s)
</td><td><br /></td></tr>
<tr><td colspan=2>
Extract package files (.zip, .tar.gz, .tar.bz2)
</td><td colspan=2>
<input type=checkbox name='extract_0' />
</td></tr>
<tr><td colspan=2>
Submit mRSL files (also .mRSL files included in packages)
</td><td colspan=2>
<input type=checkbox name='submitmrsl_0' checked />
</td></tr>
<tr><td>    
File to upload
</td><td class='righttext' colspan=3>
<input name='fileupload_0_0_0' type='file'/>
</td></tr>
<tr><td>
Optional remote filename (extra useful in windows)
</td><td class='righttext' colspan=3>
<input name='default_remotefilename_0' type='hidden' value='%(dest_dir)s'/>
<input name='remotefilename_0' type='text' size='50' value='%(dest_dir)s'/>
<input type='submit' value='Upload' name='sendfile'/>
</td></tr>
</table>
</form>
<table class='files'>
<tr class='title'><td class='centertext'>
Upload other files efficiently (using chunking).
</td></tr>
<tr><td class='centertext'>
<button id='fancydialog'>Open Upload dialog</button>
</td></tr>
</table>
</div><!-- files_form-->

<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>
    """ % {'dest_dir': '.' + os.sep}})
    
    output_objects.append({'object_type': 'html_form', 
                           'text': '''
<!-- 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>
    '''})
    return (output_objects, status)
コード例 #14
0
ファイル: ls.py プロジェクト: ucphhpc/migrid
%s
%s
%s
%s
    ''' % (cf_init, fu_init, select_all_javascript(),
           selected_file_actions_javascript())
    add_ready = '''
%s
%s
    /* wrap openFancyUpload in function to avoid event data as argument */
    $("#%s").click(function() { openFancyUpload(); });
    $("#checkall_box").click(toggleChecked);
    ''' % (cf_ready, fu_ready, open_button_id)
    # TODO: can we update style inline to avoid explicit themed_styles?
    styles = themed_styles(configuration, advanced=['jquery.fileupload.css',
                                                    'jquery.fileupload-ui.css'],
                           skin=['fileupload-ui.custom.css'],
                           user_settings=user_settings)
    styles['advanced'] += '''
    %s
    ''' % visibility_toggle
    title_entry['style'] = styles
    title_entry['script']['advanced'] += add_import
    title_entry['script']['init'] += add_init
    title_entry['script']['ready'] += add_ready
    title_entry['script']['body'] = ' class="%s"' % main_class
    output_objects.append({'object_type': 'header', 'text': page_title})

    # TODO: move to output html handler
    output_objects.append({'object_type': 'html_form',
                           'text': confirm_html(configuration)})
コード例 #15
0
def main(client_id, user_arguments_dict, environ=None):
    """Main function used by front end"""

    (configuration, logger, output_objects,
     op_name) = initialize_main_variables(client_id,
                                          op_header=False,
                                          op_title=False,
                                          op_menu=client_id)

    # Extract raw data first
    if environ is None:
        environ = os.environ
    request_url = environ.get('REQUEST_URI', '/')
    user_agent = environ.get('HTTP_USER_AGENT', '')
    user_addr = environ.get('REMOTE_ADDR', '')
    user_id = environ.get('REMOTE_USER', '')

    # IMPORTANT: use all actual args as base and override with real signature
    all_args = query_args(environ)
    defaults = signature()[1]
    all_args.update(defaults)
    (validate_status, accepted) = validate_input(user_arguments_dict,
                                                 all_args,
                                                 output_objects,
                                                 allow_rejects=False)
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    token = accepted['token'][-1]
    redirect_url = accepted['redirect_url'][-1]
    check_only = False

    # logger.debug("User: %s executing %s with redirect url %s" %
    #             (client_id, op_name, redirect_url))
    # logger.debug("env: %s" % environ)

    if not configuration.site_enable_twofactor:
        output_objects.append({
            'object_type': 'error_text',
            'text': '''2FA is not enabled on the system'''
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    if configuration.site_twofactor_strict_address \
            and not expire_twofactor_session(configuration,
                                             client_id,
                                             environ,
                                             allow_missing=True,
                                             not_user_addr=user_addr):
        logger.error("could not expire old 2FA sessions for %s" % client_id)
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            "Internal error: could not expire old 2FA sessions!"
        })

        return (output_objects, returnvalues.ERROR)

    status = returnvalues.OK

    # check that the user is already authenticated (does state file exist?)
    # or run through validation of provided time-based one-time password

    if redirect_url:
        # Build forward query string from any real non-local args
        forward_args = {}
        for (key, val) in accepted.items():
            if key not in defaults.keys() and val != ['AllowMe']:
                forward_args[key] = val
        redirect_location = redirect_url
        if forward_args:
            redirect_location += '?%s' % urllib.urlencode(forward_args, True)
        # Manual url decoding required for e.g. slashes
        redirect_location = urllib.unquote(redirect_location)
        headers = [('Status', '302 Moved'), ('Location', redirect_location)]
        logger.debug("redirect_url %s and args %s gave %s" %
                     (redirect_url, forward_args, redirect_location))
    else:
        headers = []
    twofactor_dict = load_twofactor(client_id,
                                    configuration,
                                    allow_missing=True)
    logger.debug("found twofactor_dict for %s : %s" %
                 (client_id, twofactor_dict))
    if not twofactor_dict:
        logger.warning("fall back to twofactor defaults for %s" % client_id)
        twofactor_dict = dict([
            (i, j['Value'])
            for (i, j) in twofactor_defaults(configuration).items()
        ])

    # NOTE: twofactor_defaults field availability depends on configuration
    if not redirect_url:
        # This is the 2FA setup check mode
        check_only = True
        require_twofactor = True
    elif user_id.startswith(configuration.user_mig_oid_provider) and \
            twofactor_dict.get('MIG_OID_TWOFACTOR', False):
        require_twofactor = True
    elif user_id.startswith(configuration.user_ext_oid_provider) \
            and twofactor_dict.get('EXT_OID_TWOFACTOR', False):
        require_twofactor = True
    else:
        require_twofactor = False

    # Fail gently if twofactor dependencies are unavailable
    if require_twofactor and not twofactor_available(configuration):
        logger.error("Required dependencies are missing for 2FA support")
        require_twofactor = False

    if require_twofactor:
        logger.info("detected 2FA requirement for %s on %s" %
                    (client_id, request_url))
        b32_secret = None
        if token:
            b32_secret = load_twofactor_key(client_id, configuration)
            if not b32_secret:
                logger.warning("found no saved 2FA secret for %s" % client_id)
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    "Please contact the %s admins to get your 2FA secret" %
                    configuration.short_title
                })
                return (output_objects, returnvalues.ERROR)
        # Check that user provided matching token and set cookie on success
        if token and b32_secret and verify_twofactor_token(
                configuration, client_id, b32_secret, token):
            logger.info('Accepted valid auth token from %s' % client_id)
        else:
            styles = themed_styles(configuration)
            output_objects.append({
                'object_type': 'title',
                'text': '2-Factor Authentication',
                'skipmenu': True,
                'style': styles
            })
            output_objects.append({
                'object_type': 'html_form',
                'text': twofactor_token_html(configuration)
            })
            if token:
                logger.warning('Invalid token for %s (%s vs %s) - try again' %
                               (client_id, token,
                                get_twofactor_token(configuration, client_id,
                                                    b32_secret)))
                # NOTE: we keep actual result in plain text for json extract
                output_objects.append({
                    'object_type':
                    'html_form',
                    'text':
                    '''
<div class="twofactorstatus">
<div class="error leftpad errortext">
'''
                })
                output_objects.append({
                    'object_type':
                    'text',
                    'text':
                    'Incorrect token provided - please try again'
                })
                output_objects.append({
                    'object_type': 'html_form',
                    'text': '''
</div>
</div>'''
                })
                # TODO: proper rate limit source / user here?
                time.sleep(3)
            return (output_objects, status)
    else:
        logger.info("no 2FA requirement for %s on %s" %
                    (client_id, request_url))

    # If we get here we either got correct token or verified 2FA to be disabled

    if check_only:
        logger.info("skip session init in setup check for %s" % client_id)
    else:
        cookie = Cookie.SimpleCookie()
        # TODO: reuse any existing session?
        # create a secure session cookie
        session_key = generate_session_key(configuration, client_id)
        session_start = time.time()
        cookie['2FA_Auth'] = session_key
        cookie['2FA_Auth']['path'] = '/'
        # NOTE: SimpleCookie translates expires ttl to actual date from now
        cookie['2FA_Auth']['expires'] = twofactor_cookie_ttl
        cookie['2FA_Auth']['secure'] = True
        cookie['2FA_Auth']['httponly'] = True

        # GDP only allow one active 2FA-session
        if configuration.site_enable_gdp:
            if not expire_twofactor_session(
                    configuration, client_id, environ, allow_missing=True):
                logger.error("could not expire old 2FA sessions for %s" %
                             client_id)
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    "Internal error: could not expire old 2FA sessions!"
                })
                return (output_objects, returnvalues.ERROR)

        # Create the state file to inform apache (rewrite) about auth
        # We save user info to be able to monitor and expire active sessions
        if not save_twofactor_session(configuration, client_id, session_key,
                                      user_addr, user_agent, session_start):
            logger.error("could not create 2FA session for %s" % client_id)
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                "Internal error: could not create 2FA session!"
            })
            return (output_objects, returnvalues.ERROR)

        logger.info("saved 2FA session for %s in %s" %
                    (client_id, session_key))

    if redirect_url:
        headers.append(tuple(str(cookie).split(': ', 1)))
        output_objects.append({'object_type': 'start', 'headers': headers})
        output_objects.append({'object_type': 'script_status'})
    else:
        output_objects.append({
            'object_type': 'title',
            'text': '2FA',
            'skipmenu': True
        })
        # NOTE: we keep actual result in plain text for json extract
        output_objects.append({
            'object_type':
            'html_form',
            'text':
            '''
<!-- Keep similar spacing -->
<div class="twofactorbg">
<div class="twofactorstatus">
<div class="ok leftpad">
'''
        })
        output_objects.append({
            'object_type': 'text',
            'text': 'Correct token provided!'
        })
        output_objects.append({
            'object_type':
            'html_form',
            'text':
            '''
</div>
<p>
<a href="">Test again</a> or <a href="javascript:close();">close</a> this
tab/window and proceed.
</p>
</div>
</div>'''
        })
    # logger.debug("return from %s for %s with headers: %s" %
    #             (op_name, client_id, headers))
    return (output_objects, status)
コード例 #16
0
ファイル: viewuser.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = initialize_main_variables(client_id, op_header=False)
    client_dir = client_id_dir(client_id)
    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"] = "People"

    # jquery support for confirmation-style popup:

    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" >

$(document).ready(function() {

          // init confirmation dialog
          $( "#confirm_dialog" ).dialog(
              // see http://jqueryui.com/docs/dialog/ for options
              { autoOpen: false,
                modal: true, closeOnEscape: true,
                width: 640,
                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="72" rows="10" id="confirm_input" style="display:none;"></textarea>
 </div>
""",
        }
    )

    user_list = accepted["cert_id"]

    # 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

    title_entry = find_entry(output_objects, "title")
    title_entry["text"] = "User details"
    output_objects.append({"object_type": "header", "text": "Show user details"})

    visible_user = user_visible_user_confs(configuration, client_id)
    allowed_vgrids = user_allowed_vgrids(configuration, client_id)

    for visible_user_name in user_list:
        if not visible_user_name in visible_user.keys():
            output_objects.append(
                {"object_type": "error_text", "text": "invalid user %s (%s)" % (visible_user_name, visible_user)}
            )
            continue
        user_dict = visible_user[visible_user_name]
        user_item = build_useritem_object_from_user_dict(
            configuration, visible_user_name, base_dir, user_dict, allowed_vgrids
        )
        output_objects.append(user_item)

    return (output_objects, status)
コード例 #17
0
ファイル: vgridforum.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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]
    action = accepted['action'][-1]
    thread = accepted['thread'][-1]
    msg_subject = accepted['msg_subject'][-1].strip()
    msg_body = accepted['msg_body'][-1].strip()
        
    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 forum.''' % (vgrid_name, configuration.site_vgrid_label)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    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)

    # 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_private_base,
                                            vgrid_name)) + os.sep

    forum_base = os.path.abspath(os.path.join(base_dir, '.vgridforum'))

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s Forum' % configuration.site_vgrid_label
    css_helpers = {'css_base': os.path.join(configuration.site_images, 'css'),
                   'skin_base': configuration.site_skin_base}
    title_entry['style'] = themed_styles(configuration, advanced=['forum.css'])
    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-ui.js"></script>
<script type="text/javascript" src="/images/js/jquery.confirm.js"></script>

<script type="text/javascript">
function toggle_new(form_elem_id, link_elem_id) {
    form_elem = document.getElementById(form_elem_id);
    form_focus = document.getElementById(form_elem_id + "_main");
    link_elem = document.getElementById(link_elem_id);
    if (!form_elem || !link_elem)
        return;
    if (form_elem.style.display != 'block') {
        form_elem.style.display = 'block';
        form_focus.focus();
        link_elem.style.display = 'none';
    } else {
        form_elem.style.display = 'none';
        link_elem.style.display = 'block';
        link_elem.focus();
    }
}

$(document).ready(function() {

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

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

          $("#forumtable").tablesorter({widgets: ["zebra"],
                                        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': 'sectionheader', 'text'
                          : '%s Forum for %s' % \
                           (configuration.site_vgrid_label, vgrid_name)})

    try:
        os.makedirs(forum_base)
    except:
        pass
    if not os.path.isdir(forum_base):
        output_objects.append({'object_type': 'error_text', 'text':
                               '''No forum available for %s!''' % vgrid_name})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    post_error = None
    msg = ''

    logger.info("vgridforum %s %s %s" % (vgrid_name, action, thread))
    
    if action in post_actions:
        if action == 'new_thread':
            try:
                (thread_hash, msg) = new_subject(forum_base, client_id,
                                                 msg_subject, msg_body)
                query = 'vgrid_name=%s&action=show_thread&thread=%s'\
                        % (vgrid_name,thread_hash)
                url = "%s?%s" % (os.environ['SCRIPT_URI'], query)
                notify_subscribers(configuration, forum_base, vgrid_name, '',
                                   client_id, url)
                thread = thread_hash
            except ValueError, error:
                post_error = str(error)
        elif action == 'reply':
            try:
                (thread_hash, msg) = reply(forum_base, client_id, msg_body,
                                           thread)
                query = 'vgrid_name=%s&action=show_thread&thread=%s'\
                        % (vgrid_name,thread_hash)
                url = "%s?%s" % (os.environ['SCRIPT_URI'], query)
                notify_subscribers(configuration, forum_base, vgrid_name, '',
                                   client_id, url)
                notify_subscribers(configuration, forum_base, vgrid_name,
                                   thread_hash, client_id, url)
            except ValueError, error:
                post_error = str(error)
コード例 #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)
    defaults = signature()[1]
    title_entry = find_entry(output_objects, 'title')
    label = "%s" % configuration.site_vgrid_label
    title_entry['text'] = '%s Forum' % label
    user_settings = title_entry.get('user_settings', {})
    (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]
    action = accepted['action'][-1]
    thread = accepted['thread'][-1]
    msg_subject = accepted['msg_subject'][-1].strip()
    msg_body = accepted['msg_body'][-1].strip()

    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 forum.''' % (vgrid_name, label)
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    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:
        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.vgrid_private_base, vgrid_name)) + os.sep

    forum_base = os.path.abspath(os.path.join(base_dir, '.vgridforum'))

    # TODO: can we update style inline to avoid explicit themed_styles?
    title_entry['style'] = themed_styles(configuration,
                                         advanced=['forum.css'],
                                         user_settings=user_settings)
    add_import = '''
<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.confirm.js"></script>
    '''
    add_init = '''
function toggle_new(form_elem_id, link_elem_id) {
    form_elem = document.getElementById(form_elem_id);
    form_focus = document.getElementById(form_elem_id + "_main");
    link_elem = document.getElementById(link_elem_id);
    if (!form_elem || !link_elem)
        return;
    if (form_elem.style.display != 'block') {
        form_elem.style.display = 'block';
        form_focus.focus();
        link_elem.style.display = 'none';
    } else {
        form_elem.style.display = 'none';
        link_elem.style.display = 'block';
        link_elem.focus();
    }
}
    '''
    add_ready = '''
          // init confirmation dialog
          $( "#confirm_dialog" ).dialog(
              // see http://jqueryui.com/docs/dialog/ for options
              { autoOpen: false,
                modal: true, closeOnEscape: true,
                width: 640,
                buttons: {
                   "Cancel": function() { $( "#" + name ).dialog("close"); }
                }
              });

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

          $("#forumtable").tablesorter({widgets: ["zebra"],
                                        sortList:sortOrder,
                                        textExtraction: imgTitle
                                        })
                               .tablesorterPager({ container: $("#pager"),
                                        size: %s
                                        });
          $("#pagerrefresh").click(function() { location.reload(); });
    ''' % default_pager_entries
    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':
        '''
 <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': 'sectionheader',
        'text': '%s Forum for %s' % (label, vgrid_name)
    })

    try:
        os.makedirs(forum_base)
    except:
        pass
    if not os.path.isdir(forum_base):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''No forum available for %s!''' % vgrid_name
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    post_error = None
    msg = ''

    logger.info("vgridforum %s %s %s" % (vgrid_name, action, thread))

    if action in post_actions:
        if action == 'new_thread':
            try:
                (thread_hash, msg) = new_subject(forum_base, client_id,
                                                 msg_subject, msg_body)
                query = 'vgrid_name=%s&action=show_thread&thread=%s'\
                        % (vgrid_name, thread_hash)
                url = "%s?%s" % (os.environ['SCRIPT_URI'], query)
                notify_subscribers(configuration, forum_base, vgrid_name, '',
                                   client_id, url)
                thread = thread_hash
            except ValueError, error:
                post_error = str(error)
        elif action == 'reply':
            try:
                (thread_hash, msg) = reply(forum_base, client_id, msg_body,
                                           thread)
                query = 'vgrid_name=%s&action=show_thread&thread=%s'\
                        % (vgrid_name, thread_hash)
                url = "%s?%s" % (os.environ['SCRIPT_URI'], query)
                notify_subscribers(configuration, forum_base, vgrid_name, '',
                                   client_id, url)
                notify_subscribers(configuration, forum_base, vgrid_name,
                                   thread_hash, client_id, url)
            except ValueError, error:
                post_error = str(error)
コード例 #19
0
ファイル: redb.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    defaults = signature()[1]
    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Runtime Environments'
    (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)

    # 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. 2 (admin), then 0 (name)
          var sortOrder = [[2,1],[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;
          }

          $("#runtimeenvtable").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'
                          : 'Runtime Environments'})

    output_objects.append(
        {'object_type': 'text', 'text' :
         'Runtime environments specify software/data available on resources.'
         })
    output_objects.append(
        {'object_type': 'link',
         'destination': 'docs.py?show=Runtime+Environments',
         'class': 'infolink',
         'title': 'Show information about runtime environment',
         'text': 'Documentation on runtime environments'})

    output_objects.append({'object_type': 'sectionheader', 'text'
                          : 'Existing runtime environments'})

    (status, ret) = list_runtime_environments(configuration)
    if not status:
        output_objects.append({'object_type': 'error_text', 'text'
                              : ret})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    runtimeenvironments = []
    for single_re in ret:
        (re_dict, msg) = get_re_dict(single_re, configuration)
        if not re_dict:
            output_objects.append({'object_type': 'error_text', 'text'
                                  : msg})
            return (output_objects, returnvalues.SYSTEM_ERROR)
        re_item = build_reitem_object(configuration, re_dict)
        re_name = re_item['name']
        
        re_item['viewruntimeenvlink'] = {'object_type': 'link',
                                         'destination': "showre.py?re_name=%s" % re_name,
                                         'class': 'infolink',
                                         'title': 'View %s runtime environment' % re_name, 
                                         'text': ''}
        if client_id == re_item['creator']:
            js_name = 'delete%s' % hexlify(re_name)
            helper = html_post_helper(js_name, 'deletere.py',
                                      {'re_name': re_name})
            output_objects.append({'object_type': 'html_form', 'text': helper})
            re_item['ownerlink'] = {'object_type': 'link',
                                    'destination':
                                    "javascript: confirmDialog(%s, '%s');"\
                                    % (js_name, 'Really delete %s?' % re_name),
                                    'class': 'removelink',
                                    'title': 'Delete %s runtime environment' % re_name, 
                                    'text': ''}
        runtimeenvironments.append(re_item)

    output_objects.append({'object_type': 'table_pager', 'entry_name': 'runtime envs',
                           'default_entries': default_pager_entries})
    output_objects.append({'object_type': 'runtimeenvironments',
                          'runtimeenvironments': runtimeenvironments})

    if configuration.site_swrepo_url:
        output_objects.append({'object_type': 'sectionheader', 'text': 'Software Packages'})
        output_objects.append({'object_type': 'link',
                               'destination': configuration.site_swrepo_url,
                               'class': 'swrepolink',
                               'title': 'Browse available software packages',
                               'text': 'Open software catalogue for %s' % \
                               configuration.short_title,
                               })

    output_objects.append({'object_type': 'sectionheader', 'text': 'Additional Runtime Environments'})
    output_objects.append({'object_type': 'link',
                           'destination': 'adminre.py',
                           'class': 'addlink',
                           'title': 'Specify a new runtime environment', 
                           'text': 'Create a new runtime environment'})

    return (output_objects, returnvalues.OK)
コード例 #20
0
ファイル: grid_monitor.py プロジェクト: heromod/migrid
def create_monitor(vgrid_name):
    """Write monitor HTML file for vgrid_name"""

    html_file = os.path.join(configuration.vgrid_home, vgrid_name, "%s.html" % configuration.vgrid_monitor)

    print "collecting statistics for VGrid %s" % vgrid_name
    sleep_secs = configuration.sleep_secs
    slackperiod = configuration.slackperiod
    now = time.asctime(time.localtime())

    html_vars = {
        "sleep_secs": sleep_secs,
        "vgrid_name": vgrid_name,
        "logo_url": "/images/logo.jpg",
        "now": now,
        "short_title": configuration.short_title,
    }

    html = get_cgi_html_header(
        configuration,
        "%(short_title)s Monitor, VGrid %(vgrid_name)s" % html_vars,
        "",
        True,
        """<meta http-equiv="refresh" content="%(sleep_secs)s" />
        """
        % html_vars,
        themed_styles(configuration),
        """
<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>
        """,
        "",
        False,
    )
    html += (
        """
<!-- end of raw header: this line is used by showvgridmonitor -->
<h1>Statistics/monitor for the %(vgrid_name)s VGrid</h1>
<div class="generatornote smallcontent">
This page was generated %(now)s (automatic refresh every %(sleep_secs)s secs).
</div>
"""
        % html_vars
    )

    # loop and get totals

    parse_count = 0
    queued_count = 0
    frozen_count = 0
    executing_count = 0
    finished_count = 0
    failed_count = 0
    retry_count = 0
    canceled_count = 0

    cpucount_requested = 0
    cpucount_done = 0
    nodecount_requested = 0
    nodecount_done = 0
    cputime_requested = 0
    cputime_done = 0
    used_walltime = 0
    disk_requested = 0
    disk_done = 0
    memory_requested = 0
    memory_done = 0
    runtimeenv_dict = {"": 0}
    runtimeenv_requested = 0
    runtimeenv_done = 0

    number_of_jobs = 0
    up_count = 0
    down_count = 0
    slack_count = 0

    job_assigned = 0
    job_assigned_cpus = 0

    gstat = GridStat(configuration, logger)

    runtimeenv_dict = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "RUNTIMEENVIRONMENT", {})

    parse_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "PARSE")
    queued_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "QUEUED")
    frozen_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "FROZEN")
    executing_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "EXECUTING")
    failed_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "FAILED")
    retry_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "RETRY")
    canceled_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "CANCELED")
    expired_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "EXPIRED")
    finished_count = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "FINISHED")

    nodecount_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "NODECOUNT_REQ")
    nodecount_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "NODECOUNT_DONE")
    cputime_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "CPUTIME_REQ")
    cputime_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "CPUTIME_DONE")

    used_walltime = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "USED_WALLTIME")

    if used_walltime == 0:
        used_walltime = datetime.timedelta(0)

    used_walltime = format_timedelta(used_walltime)

    disk_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "DISK_REQ")
    disk_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "DISK_DONE")
    memory_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "MEMORY_REQ")
    memory_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "MEMORY_DONE")
    cpucount_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "CPUCOUNT_REQ")
    cpucount_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "CPUCOUNT_DONE")
    runtimeenv_requested = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "RUNTIMEENVIRONMENT_REQ")
    runtimeenv_done = gstat.get_value(gstat.VGRID, vgrid_name.upper(), "RUNTIMEENVIRONMENT_DONE")

    number_of_jobs = parse_count
    number_of_jobs += queued_count
    number_of_jobs += frozen_count
    number_of_jobs += expired_count
    number_of_jobs += canceled_count
    number_of_jobs += failed_count
    number_of_jobs += executing_count
    number_of_jobs += finished_count
    number_of_jobs += retry_count

    html_vars = {
        "parse_count": parse_count,
        "queued_count": queued_count,
        "frozen_count": frozen_count,
        "executing_count": executing_count,
        "failed_count": failed_count,
        "retry_count": retry_count,
        "canceled_count": canceled_count,
        "expired_count": expired_count,
        "finished_count": finished_count,
        "number_of_jobs": number_of_jobs,
        "cpucount_requested": cpucount_requested,
        "cpucount_done": cpucount_done,
        "nodecount_requested": nodecount_requested,
        "nodecount_done": nodecount_done,
        "cputime_requested": cputime_requested,
        "cputime_done": cputime_done,
        "used_walltime": used_walltime,
        "disk_requested": disk_requested,
        "disk_done": disk_done,
        "memory_requested": memory_requested,
        "memory_done": memory_done,
        "runtimeenv_requested": runtimeenv_requested,
        "runtimeenv_done": runtimeenv_done,
    }

    html += (
        """<h2>Job Stats</h2><table class=monitorstats><tr><td>
<table class=monitorjobs><tr class=title><td>Job State</td><td>Number of jobs</td></tr>
<tr><td>Parse</td><td>%(parse_count)s</td></tr>
<tr><td>Queued</td><td>%(queued_count)s</td></tr>
<tr><td>Frozen</td><td>%(frozen_count)s</td></tr>
<tr><td>Executing</td><td>%(executing_count)s</td></tr>
<tr><td>Failed</td><td>%(failed_count)s</td></tr>
<tr><td>Retry</td><td>%(retry_count)s</td></tr>
<tr><td>Canceled</td><td>%(canceled_count)s</td></tr>
<tr><td>Expired</td><td>%(expired_count)s</td></tr>
<tr><td>Finished</td><td>%(finished_count)s</td></tr>
<tr><td>Total</td><td>%(number_of_jobs)s</td></tr>
</table>
</td><td>
<table class=monitorresreq>
<tr class=title><td>Requirement</td><td>Requested</td><td>Done</td></tr>
<tr><td>Cpucount</td><td>%(cpucount_requested)s</td><td>%(cpucount_done)s</td></tr>
<tr><td>Nodecount</td><td>%(nodecount_requested)s</td><td>%(nodecount_done)s</td></tr>
<tr><td>Cputime</td><td>%(cputime_requested)s</td><td>%(cputime_done)s</td></tr>
<tr><td>GB Disk</td><td>%(disk_requested)s</td><td>%(disk_done)s</td></tr>
<tr><td>MB Memory</td><td>%(memory_requested)s</td><td>%(memory_done)s</td></tr>
<tr><td>Runtime Envs</td><td>%(runtimeenv_requested)s</td><td>%(runtimeenv_done)s</td></tr>
<tr><td>Used Walltime</td><td colspan='2'>%(used_walltime)s</td></tr>
</table><br />
</td><td>
<div class=monitorruntimeenvdetails>
<table class=monitorruntimeenvdone>
<tr class=title><td>Runtime Envs Done</td><td></td></tr>
"""
        % html_vars
    )

    if len(runtimeenv_dict.keys()) < 1:

        # No runtimeenv requests

        html += "<tr><td></td><td>-</td></tr>\n"
    else:
        for entry in runtimeenv_dict.keys():
            if not entry == "":
                html += "<tr><td>" + entry + "</td><td>" + str(runtimeenv_dict[entry]) + "</td></tr>\n"

    total_number_of_exe_resources, total_number_of_store_resources = 0, 0
    total_number_of_exe_cpus, total_number_of_store_gigs = 0, 0

    vgrid_name_list = vgrid_name.split("/")
    current_dir = ""

    exes, stores = "", ""
    for vgrid_name_part in vgrid_name_list:
        current_dir = os.path.join(current_dir, vgrid_name_part)
        abs_mon_dir = os.path.join(configuration.vgrid_home, current_dir)
        # print 'dir: %s' % abs_mon_dir
        # Potential race - just ignore if it disappeared
        try:
            sorted_names = os.listdir(abs_mon_dir)
        except OSError:
            continue
        sorted_names.sort()
        for filename in sorted_names:
            # print filename
            if filename.startswith("monitor_last_request_"):

                # read last request helper file

                mon_file_name = os.path.join(abs_mon_dir, filename)
                print "found " + mon_file_name
                last_request_dict = unpickle(mon_file_name, logger)
                if not last_request_dict:
                    print "could not open and unpickle: " + mon_file_name
                    continue

                difference = datetime.datetime.now() - last_request_dict["CREATED_TIME"]
                days = str(difference.days)
                hours = str(difference.seconds / 3600)
                minutes = str((difference.seconds % 3600) / 60)
                seconds = str((difference.seconds % 60) % 60)

                if last_request_dict.has_key("CPUTIME"):
                    cputime = last_request_dict["CPUTIME"]
                elif last_request_dict.has_key("cputime"):
                    cputime = last_request_dict["cputime"]
                else:
                    print "ERROR: last request does not contain cputime field!: %s" % last_request_dict
                    continue

                try:
                    cpusec = int(cputime)
                except ValueError:
                    try:
                        cpusec = int(float(cputime))
                    except ValueError, verr:
                        print "ERROR: failed to parse cputime %s: %s" % (cputime, verr)

                # Include execution delay guesstimate for strict fill
                # LRMS resources

                try:
                    delay = int(last_request_dict["EXECUTION_DELAY"])
                except KeyError:
                    delay = 0
                except ValueError:
                    delay = 0

                time_remaining = (
                    last_request_dict["CREATED_TIME"]
                    + datetime.timedelta(seconds=cpusec)
                    + datetime.timedelta(seconds=delay)
                ) - datetime.datetime.now()
                days_rem = str(time_remaining.days)
                hours_rem = str(time_remaining.seconds / 3600)
                minutes_rem = str((time_remaining.seconds % 3600) / 60)
                seconds_rem = str((time_remaining.seconds % 60) % 60)

                if time_remaining.days < -7:
                    try:
                        print "removing: %s as we havent seen him for %s days." % (
                            mon_file_name,
                            abs(time_remaining).days,
                        )
                        os.remove(mon_file_name)
                    except Exception, err:
                        print "could not remove: '%s' Error: %s" % (mon_file_name, str(err))
                    pass
                else:
                    unique_res_name_and_exe_list = filename.split("monitor_last_request_", 1)
                    if cpusec == 0:
                        resource_status = "unavailable"
                    elif time_remaining.days < 0:

                        # time_remaining.days < 0 means that we have passed the specified time

                        time_rem_abs = abs(time_remaining)
                        if time_rem_abs.days == 0 and int(time_rem_abs.seconds) < int(slackperiod):
                            resource_status = "slack"
                            slack_count = slack_count + 1
                        else:
                            resource_status = "offline"
                            down_count = down_count + 1
                    else:
                        resource_status = "online"
                        up_count = up_count + 1

                    exes += "<tr>"
                    exes += "<td><img src=/images/status-icons/%s.png /></td>" % resource_status
                    public_id = unique_res_name_and_exe_list[1]
                    if last_request_dict["RESOURCE_CONFIG"].get("ANONYMOUS", True):
                        public_id = anon_resource_id(public_id)
                    public_name = last_request_dict["RESOURCE_CONFIG"].get("PUBLICNAME", "")
                    resource_parts = public_id.split("_", 2)
                    resource_name = "<a href='viewres.py?unique_resource_name=%s'>%s</a>" % (
                        resource_parts[0],
                        resource_parts[0],
                    )
                    if public_name:
                        resource_name += "<br />(alias %s)" % public_name
                    else:
                        resource_name += "<br />(no alias)"
                    resource_name += "<br />%s" % resource_parts[1]
                    exes += "<td>%s</td>" % resource_name

                    exes += "<td>%s<br />(%sd %sh %sm %ss ago)</td>" % (
                        time.asctime(last_request_dict["CREATED_TIME"].timetuple()),
                        days,
                        hours,
                        minutes,
                        seconds,
                    )
                    exes += "<td>" + vgrid_name + "</td>"
                    runtime_envs = last_request_dict["RESOURCE_CONFIG"]["RUNTIMEENVIRONMENT"]
                    re_list_text = ", ".join([i[0] for i in runtime_envs])
                    exes += '<td title="%s">' % re_list_text + str(len(runtime_envs)) + "</td>"
                    exes += (
                        "<td>"
                        + str(last_request_dict["RESOURCE_CONFIG"]["CPUTIME"])
                        + "</td><td>"
                        + str(last_request_dict["RESOURCE_CONFIG"]["NODECOUNT"])
                        + "</td><td>"
                        + str(last_request_dict["RESOURCE_CONFIG"]["CPUCOUNT"])
                        + "</td><td>"
                        + str(last_request_dict["RESOURCE_CONFIG"]["DISK"])
                        + "</td><td>"
                        + str(last_request_dict["RESOURCE_CONFIG"]["MEMORY"])
                        + "</td><td>"
                        + str(last_request_dict["RESOURCE_CONFIG"]["ARCHITECTURE"])
                        + "</td>"
                    )
                    exes += (
                        "<td>" + last_request_dict["STATUS"] + "</td><td>" + str(last_request_dict["CPUTIME"]) + "</td>"
                    )

                    exes += "<td class=status_%s>" % resource_status
                    if "unavailable" == resource_status:
                        exes += "-"
                    elif "slack" == resource_status:
                        exes += "Within slack period (%s < %s secs)" % (time_rem_abs.seconds, slackperiod)
                    elif "offline" == resource_status:
                        exes += "down?"
                    else:
                        exes += "%sd, %sh, %sm, %ss" % (days_rem, hours_rem, minutes_rem, seconds_rem)
                    exes += "</td>"

                    exes += "</tr>\n"
                    if last_request_dict["STATUS"] == "Job assigned":
                        job_assigned = job_assigned + 1
                        job_assigned_cpus = job_assigned_cpus + int(
                            last_request_dict["RESOURCE_CONFIG"]["NODECOUNT"]
                        ) * int(last_request_dict["RESOURCE_CONFIG"]["CPUCOUNT"])

                    total_number_of_exe_resources += 1
                    total_number_of_exe_cpus += int(last_request_dict["RESOURCE_CONFIG"]["NODECOUNT"]) * int(
                        last_request_dict["RESOURCE_CONFIG"]["CPUCOUNT"]
                    )
            elif filename.startswith("monitor_last_status_"):

                # store must be linked to this vgrid, not only parent vgrid:
                # inheritance only covers access, not automatic participation

                if current_dir != vgrid_name:
                    continue

                # read last resource action status file

                mon_file_name = os.path.join(abs_mon_dir, filename)
                print "found " + mon_file_name
                last_status_dict = unpickle(mon_file_name, logger)
                if not last_status_dict:
                    print "could not open and unpickle: " + mon_file_name
                    continue

                difference = datetime.datetime.now() - last_status_dict["CREATED_TIME"]
                days = str(difference.days)
                hours = str(difference.seconds / 3600)
                minutes = str((difference.seconds % 3600) / 60)
                seconds = str((difference.seconds % 60) % 60)

                if last_status_dict["STATUS"] == "stopped":
                    time_stopped = datetime.datetime.now() - last_status_dict["CREATED_TIME"]
                    if time_stopped.days > 7:
                        try:
                            print "removing: %s as we havent seen him for %s days." % (
                                mon_file_name,
                                abs(time_stopped).days,
                            )
                            os.remove(mon_file_name)
                        except Exception, err:
                            print "could not remove: '%s' Error: %s" % (mon_file_name, str(err))
                        continue
コード例 #21
0
ファイル: dashboard.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""
    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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'] = 'Dashboard'

    # 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" >

$(document).ready(function() {

          function roundNumber(num, dec) {
              var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
              return result;
          }

          $("#jobs_stats").addClass("spinner iconspace");
          $("#jobs_stats").html("Loading job stats...");
          $("#res_stats").addClass("spinner iconspace");
          $("#res_stats").html("Loading resource stats...");
          $("#disk_stats").addClass("spinner iconspace");
          $("#disk_stats").html("Loading disk stats...");
          $("#cert_stats").addClass("spinner iconspace");
          $("#cert_stats").html("Loading certificate information...");
          /* Run certificate request in the background and handle as soon as results come in */
          $.ajax({
              url: "userstats.py?output_format=json;stats=certificate",
              type: "GET",
              dataType: "json",
              cache: false,
              success: function(jsonRes, textStatus) {
                  var i = 0;
                  var certificate = null;
                  var renew_days = 30;
                  var day_msecs = 24*60*60*1000;
                  // Grab results from json response and place them in resource status.
                  for(i=0; i<jsonRes.length; i++) {
                      if (jsonRes[i].object_type == "user_stats") {    
                          certificate = jsonRes[i].certificate;
                          $("#cert_stats").removeClass("spinner iconspace");
                          $("#cert_stats").empty();
                          if (certificate.expire == -1) {
                              break;
                          }
                          var expire_date = new Date(certificate.expire);
                          $("#cert_stats").append("Your user certificate expires on " +
                          expire_date + ".");
                          // Use date from time diff in ms to avoid calendar mangling
                          var show_renew = new Date(expire_date.getTime() - renew_days*day_msecs);
                          if(new Date().getTime() > show_renew.getTime()) {
                              $("#cert_stats").addClass("warningtext");
                              $("#cert_stats").append("&nbsp;<a class=\'certrenewlink\' href=\'reqcert.py\'>Renew certificate</a>.");
                          }
                          break;
                      }
                  }
              }
          });
          /* Run jobs request in the background and handle as soon as results come in */
          $.ajax({
              url: "userstats.py?output_format=json;stats=jobs",
              type: "GET",
              dataType: "json",
              cache: false,
              success: function(jsonRes, textStatus) {
                  var i = 0;
                  var jobs = null;
                  // Grab results from json response and place them in job status.
                  for(i=0; i<jsonRes.length; i++) {
                      if (jsonRes[i].object_type == "user_stats") {    
                          jobs = jsonRes[i].jobs;
                          //alert("inspect stats result: " + jobs);
                          $("#jobs_stats").removeClass("spinner iconspace");
                          $("#jobs_stats").empty();
                          $("#jobs_stats").append("You have submitted a total of " + jobs.total +
                              " jobs: " + jobs.parse + " parse, " + jobs.queued + " queued, " +
                              jobs.frozen + " frozen, " + jobs.executing + " executing, " +
                              jobs.finished + " finished, " + jobs.retry + " retry, " +
                              jobs.canceled + " canceled, " + jobs.expired + " expired and " +
                              jobs.failed + " failed.");
                         break;
                      }
                  }   
              }
          });
          /* Run resources request in the background and handle as soon as results come in */
          $.ajax({
              url: "userstats.py?output_format=json;stats=resources",
              type: "GET",
              dataType: "json",
              cache: false,
              success: function(jsonRes, textStatus) {
                  var i = 0;
                  var resources = null;
                  // Grab results from json response and place them in resource status.
                  for(i=0; i<jsonRes.length; i++) {
                      if (jsonRes[i].object_type == "user_stats") {    
                          resources = jsonRes[i].resources;
                          //alert("inspect resources stats result: " + resources);
                          $("#res_stats").removeClass("spinner iconspace");
                          $("#res_stats").empty();
                          $("#res_stats").append(resources.resources + " resources providing " +
                          resources.exes + " execution units in total allow execution of your jobs.");
                          break;
                      }
                  }
              }
          });
          /* Run disk request in the background and handle as soon as results come in */
          $.ajax({
              url:"userstats.py?output_format=json;stats=disk",
              type: "GET",
              dataType: "json",
              cache: false,
              success: function(jsonRes, textStatus) {
                  var i = 0;
                  var disk = null;
                  // Grab results from json response and place them in resource status.
                  for(i=0; i<jsonRes.length; i++) {
                      if (jsonRes[i].object_type == "user_stats") {    
                          disk = jsonRes[i].disk;
                          //alert("inspect disk stats result: " + disk);
                          $("#disk_stats").removeClass("spinner iconspace");
                          $("#disk_stats").empty();
                          $("#disk_stats").append("Your own " + disk.own_files +" files and " +
                              disk.own_directories + " directories take up " + roundNumber(disk.own_megabytes, 2) +
                              " MB in total and you additionally share " + disk.vgrid_files +
                              " files and " + disk.vgrid_directories + " directories of " +
                              roundNumber(disk.vgrid_megabytes, 2) + " MB in total.");
                          break;
                      }
                  }
              }
          });
     }
);
</script>
'''

    output_objects.append({'object_type': 'header', 'text': 'Dashboard'})
    output_objects.append({'object_type': 'sectionheader', 'text' :
                           "Welcome to the %s" % \
                           configuration.site_title})
    welcome_line = "Hi %s" % extract_field(client_id, "full_name")
    output_objects.append({'object_type': 'text', 'text': welcome_line})
    dashboard_info = """
This is your private entry page or your dashboard where you can get a
quick status overview and find pointers to help and documentation.
When you are logged in with your user credentials/certificate, as you are now,
you can navigate your pages using the menu on the left.
""" % os.environ
    output_objects.append({'object_type': 'text', 'text': dashboard_info})

    output_objects.append({'object_type': 'sectionheader', 'text':
                           "Your Status"})
    output_objects.append({'object_type': 'html_form', 'text': '''
<p>
This is a general status overview for your Grid activities. Please note that some
of the numbers are cached for a while to keep server load down.
</p>
<div id="jobs_stats"><!-- for jquery --></div><br />
<div id="res_stats"><!-- for jquery --></div><br />
<div id="disk_stats"><!-- for jquery --></div><br />
<div id="cert_stats"><!-- for jquery --></div><br />
<div id="cert_renew" class="hidden"><a href="reqcert.py">renew certificate</a>
</div>
'''})

    output_objects.append({'object_type': 'sectionheader', 'text' :
                           'Documentation and Help'})
    online_help = """
%s includes some built-in documentation like the
""" % configuration.site_title
    output_objects.append({'object_type': 'text', 'text': online_help})
    output_objects.append({'object_type': 'link', 'destination': 'docs.py',
                           'class': 'infolink', 'title': 'built-in documentation',
                           'text': 'Docs page'})
    project_info = """
but additional help, background information and tutorials are available in the
"""
    output_objects.append({'object_type': 'text', 'text': project_info})
    output_objects.append({'object_type': 'link', 'destination':
                           configuration.site_external_doc,
                           'class': 'urllink', 'title': 'external documentation',
                           'text': 'external %s documentation' % \
                           configuration.site_title})
    
    output_objects.append({'object_type': 'sectionheader', 'text' :
                           "Personal Settings"})
    settings_info = """
You can customize your personal pages by opening the Settings
page from the navigation menu and entering personal preferences. In that way you
can completely redecorate your interface and configure things like notification,
profile visibility and remote file access.
"""
    output_objects.append({'object_type': 'text', 'text': settings_info})

    #env_info = """Env %s""" % os.environ
    #output_objects.append({'object_type': 'text', 'text': env_info})

    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)
    client_dir = client_id_dir(client_id)
    status = returnvalues.OK
    defaults = signature()[1]
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
    )
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    show_description = accepted['description'][-1].lower() == 'true'

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

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

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

    template_path = os.path.join(base_dir, default_mrsl_filename)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Submit Job'
    user_settings = title_entry.get('user_settings', {})
    output_objects.append({'object_type': 'header', 'text': 'Submit Job'})
    default_mrsl = get_default_mrsl(template_path)
    if not user_settings or not user_settings.has_key('SUBMITUI'):
        logger.info('Settings dict does not have SUBMITUI key - using default')
        submit_style = configuration.submitui[0]
    else:
        submit_style = user_settings['SUBMITUI']

    # We generate all 3 variants of job submission (fields, textarea, files),
    # initially hide them and allow to switch between them using js.

    # could instead extract valid prefixes as in settings.py
    # (means: by "eval" from configuration). We stick to hard-coding.
    submit_options = ['fields_form', 'textarea_form', 'files_form']

    open_button_id = 'open_fancy_upload'
    form_method = 'post'
    csrf_limit = get_csrf_limit(configuration)
    fill_helpers = {
        'dest_dir': '.' + os.sep,
        'fancy_open': open_button_id,
        'default_mrsl': default_mrsl,
        'form_method': form_method,
        'csrf_field': csrf_field,
        'csrf_limit': csrf_limit
    }
    target_op = 'uploadchunked'
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    (add_import, add_init, add_ready) = fancy_upload_js(configuration,
                                                        csrf_token=csrf_token)
    add_init += '''
    submit_options = %s;

    function setDisplay(this_id, new_d) {
        //console.log("setDisplay with: "+this_id);
        el = document.getElementById(this_id)
        if (el == undefined || el.style == undefined) {
            console.log("failed to locate display element: "+this_id);
            return; // avoid js null ref errors
        }
        el.style.display=new_d;
    }

    function switchTo(name) {
        //console.log("switchTo: "+name);
        for (o=0; o < submit_options.length; o++) {
            if (name == submit_options[o]) {
                setDisplay(submit_options[o],"block");
            } else {
                setDisplay(submit_options[o],"none");
            }
        }
    }
    ''' % submit_options
    add_ready += '''
    switchTo("%s");
    setUploadDest("%s");
    /* wrap openFancyUpload in function to avoid event data as argument */
    $("#%s").click(function() { openFancyUpload(); });
    ''' % (submit_style + "_form", fill_helpers['dest_dir'], open_button_id)
    fancy_dialog = fancy_upload_html(configuration)
    # TODO: can we update style inline to avoid explicit themed_styles?
    title_entry['style'] = themed_styles(
        configuration,
        base=['jquery.fileupload.css', 'jquery.fileupload-ui.css'],
        skin=['fileupload-ui.custom.css'],
        user_settings=user_settings)
    title_entry['script']['advanced'] += add_import
    title_entry['script']['init'] += add_init
    title_entry['script']['ready'] += add_ready

    output_objects.append({
        'object_type':
        'text',
        'text':
        'This page is used to submit jobs to the grid.'
    })

    output_objects.append({
        'object_type':
        'verbatim',
        'text':
        '''
There are %s interface styles available that you can choose among:''' %
        len(submit_options)
    })

    links = []
    for opt in submit_options:
        name = opt.split('_', 2)[0]
        links.append({
            'object_type': 'link',
            'destination': "javascript:switchTo('%s')" % opt,
            'class': 'submit%slink iconspace' % name,
            'title': 'Switch to %s submit interface' % name,
            'text': '%s style' % name,
        })
    output_objects.append({'object_type': 'multilinkline', 'links': links})

    output_objects.append({
        'object_type':
        'text',
        'text':
        '''
Please note that changes to the job description are *not* automatically
transferred if you switch style.'''
    })

    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '<div id="fields_form" style="display:none;">\n'
    })

    # Fields
    output_objects.append({
        'object_type':
        'sectionheader',
        'text':
        'Please fill in your job description in the fields'
        ' below:'
    })
    output_objects.append({
        'object_type':
        'text',
        'text':
        """
Please fill in one or more fields below to define your job before hitting
Submit Job at the bottom of the page.
Empty fields will simply result in the default value being used and each field
is accompanied by a help link providing further details about the field."""
    })

    fill_helpers.update({'fancy_dialog': fancy_dialog})
    target_op = 'submitfields'
    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':
        """
<div class='submitjob'>
<form method='%(form_method)s' action='%(target_op)s.py'> 
<input type='hidden' name='%(csrf_field)s' value='%(csrf_token)s' />
""" % fill_helpers
    })
    show_fields = get_job_specs(configuration)
    try:
        parsed_mrsl = dict(parse_lines(default_mrsl))
    except:
        parsed_mrsl = {}

    # Find allowed VGrids and Runtimeenvironments and add them to
    # configuration object for automated choice handling

    vgrid_access = user_vgrid_access(configuration, client_id) + \
        [any_vgrid]
    vgrid_access.sort()
    configuration.vgrids = vgrid_access
    (re_status, allowed_run_envs) = list_runtime_environments(configuration)
    if not re_status:
        logger.error('Failed to extract allowed runtime envs: %s' %
                     allowed_run_envs)
        allowed_run_envs = []
    allowed_run_envs.sort()
    configuration.runtimeenvironments = allowed_run_envs
    # TODO: next call is slow because we walk and reload all pickles
    user_res = user_allowed_res_exes(configuration, client_id)

    # Add valid MAXFILL values to automated choice handling

    configuration.maxfills = [keyword_all] + maxfill_fields

    # Allow any exe unit on all allowed resources

    allowed_resources = ['%s_*' % res for res in user_res.keys()]
    allowed_resources.sort()
    configuration.resources = allowed_resources
    field_size = 30
    area_cols = 80
    area_rows = 5

    for (field, spec) in show_fields:
        title = spec['Title']
        if show_description:
            description = '%s<br />' % spec['Description']
        else:
            description = ''
        field_type = spec['Type']
        # Use saved value and fall back to default if it is missing
        saved = parsed_mrsl.get('::%s::' % field, None)
        if saved:
            if not spec['Type'].startswith('multiple'):
                default = saved[0]
            else:
                default = saved
        else:
            default = spec['Value']
        # Hide sandbox field if sandboxes are disabled
        if field == 'SANDBOX' and not configuration.site_enable_sandboxes:
            continue
        if 'invisible' == spec['Editor']:
            continue
        if 'custom' == spec['Editor']:
            continue
        output_objects.append({
            'object_type':
            'html_form',
            'text':
            """
<b>%s:</b>&nbsp;<a class='infolink iconspace' href='docs.py?show=job#%s'>
help</a><br />
%s""" % (title, field, description)
        })

        if 'input' == spec['Editor']:
            if field_type.startswith('multiple'):
                output_objects.append({
                    'object_type':
                    'html_form',
                    'text':
                    """
<textarea class='fillwidth padspace' name='%s' cols='%d' rows='%d'>%s</textarea><br />
""" % (field, area_cols, area_rows, '\n'.join(default))
                })
            elif field_type == 'int':
                output_objects.append({
                    'object_type':
                    'html_form',
                    'text':
                    """
<input type='number' name='%s' size='%d' value='%s' min=0 required pattern='[0-9]+' /><br />
""" % (field, field_size, default)
                })
            else:
                output_objects.append({
                    'object_type':
                    'html_form',
                    'text':
                    """
<input type='text' name='%s' size='%d' value='%s' /><br />
""" % (field, field_size, default)
                })
        elif 'select' == spec['Editor']:
            choices = available_choices(configuration, client_id, field, spec)
            res_value = default
            value_select = ''
            if field_type.startswith('multiple'):
                value_select += '<div class="scrollselect">'
                for name in choices:
                    # Blank default value does not make sense here
                    if not str(name):
                        continue
                    selected = ''
                    if str(name) in res_value:
                        selected = 'checked'
                    value_select += '''
                        <input type="checkbox" name="%s" %s value=%s>%s<br />
                        ''' % (field, selected, name, name)
                value_select += '</div>\n'
            else:
                value_select += "<select name='%s'>\n" % field
                for name in choices:
                    selected = ''
                    if str(res_value) == str(name):
                        selected = 'selected'
                    display = "%s" % name
                    if display == '':
                        display = ' '
                    value_select += """<option %s value='%s'>%s</option>\n""" \
                                    % (selected, name, display)
                value_select += """</select><br />\n"""
            output_objects.append({
                'object_type': 'html_form',
                'text': value_select
            })
        output_objects.append({'object_type': 'html_form', 'text': "<br />"})

    output_objects.append({
        'object_type':
        'html_form',
        'text':
        """
<br />
<table class='centertext'>
<tr><td><input type='submit' value='Submit Job' />
<input type='checkbox' name='save_as_default'> Save as default job template
</td></tr>
</table>
<br />
</form>
</div>
"""
    })
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
</div><!-- fields_form-->
<div id="textarea_form" style="display:none;">
'''
    })

    # Textarea
    output_objects.append({
        'object_type':
        'sectionheader',
        'text':
        'Please enter your mRSL job description below:'
    })
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        """
<div class='smallcontent'>
Job descriptions can use a wide range of keywords to specify job requirements
and actions.<br />
Each keyword accepts one or more values of a particular type.<br />
The full list of keywords with their default values and format is available in
the on-demand <a href='docs.py?show=job'>mRSL Documentation</a>.
<p>
Actual examples for inspiration:
<a href=/public/cpuinfo.mRSL>CPU Info</a>,
<a href=/public/basic-io.mRSL>Basic I/O</a>,
<a href=/public/notification.mRSL>Job Notification</a>,
<a href=/public/povray.mRSL>Povray</a> and
<a href=/public/vcr.mRSL>VCR</a>
</div>
    """
    })

    target_op = 'textarea'
    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':
        """
<!-- 
Please note that textarea.py chokes if no nonempty KEYWORD_X_Y_Z fields 
are supplied: thus we simply send a bogus jobname which does nothing
-->
<form method='%(form_method)s' action='%(target_op)s.py'> 
<input type='hidden' name='%(csrf_field)s' value='%(csrf_token)s' />
<table class='submitjob'>
<tr><td class='centertext'>
<input type=hidden name=jobname_0_0_0 value=' ' />
<textarea class='fillwidth padspace' rows='25' name='mrsltextarea_0'>
%(default_mrsl)s
</textarea>
</td></tr>
<tr><td class='centertext'>
<input type='submit' value='Submit Job' />
<input type='checkbox' name='save_as_default' >Save as default job template
</td></tr>
</table>
</form>
""" % fill_helpers
    })

    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
</div><!-- textarea_form-->
<div id="files_form" style="display:none;">
'''
    })
    # Upload form

    output_objects.append({
        'object_type':
        'sectionheader',
        'text':
        'Please upload your job file or packaged job files'
        ' below:'
    })
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        """
<form enctype='multipart/form-data' method='%(form_method)s'
    action='%(target_op)s.py'> 
<input type='hidden' name='%(csrf_field)s' value='%(csrf_token)s' />
<table class='files'>
<tr class='title'><td class='centertext' colspan=4>
Upload job files
</td></tr>
<tr><td colspan=3>
Upload file to current directory (%(dest_dir)s)
</td><td><br /></td></tr>
<tr><td colspan=2>
Extract package files (.zip, .tar.gz, .tar.bz2)
</td><td colspan=2>
<input type=checkbox name='extract_0' />
</td></tr>
<tr><td colspan=2>
Submit mRSL files (also .mRSL files included in packages)
</td><td colspan=2>
<input type=checkbox name='submitmrsl_0' checked />
</td></tr>
<tr><td>    
File to upload
</td><td class='righttext' colspan=3>
<input name='fileupload_0_0_0' type='file'/>
</td></tr>
<tr><td>
Optional remote filename (extra useful in windows)
</td><td class='righttext' colspan=3>
<input name='default_remotefilename_0' type='hidden' value='%(dest_dir)s'/>
<input name='remotefilename_0' type='text' size='50' value='%(dest_dir)s'/>
<input type='submit' value='Upload' name='sendfile'/>
</td></tr>
</table>
</form>
<table class='files'>
<tr class='title'><td class='centertext'>
Upload other files efficiently (using chunking).
</td></tr>
<tr><td class='centertext'>
<button id='%(fancy_open)s'>Open Upload dialog</button>
</td></tr>
</table>
</div><!-- files_form-->

%(fancy_dialog)s
""" % fill_helpers
    })

    return (output_objects, status)
コード例 #23
0
ファイル: people.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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'] = 'People'

    # 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: 640,
                buttons: {
                   "Cancel": function() { $( "#" + name ).dialog("close"); }
                }
              });

          // table initially sorted by 0 (name)
          var sortOrder = [[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;
          }

          $("#usertable").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'
                          : 'People'})

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

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

    visible_user = user_visible_user_confs(configuration, client_id)
    allow_vgrids = user_allowed_vgrids(configuration, client_id)
    anon_map = anon_to_real_user_map(configuration.user_home)
    if not visible_user:
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'no users found!'})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    users = []
    for (visible_user_id, user_dict) in visible_user.items():
        user_id = visible_user_id
        if visible_user_id in anon_map.keys():
            user_id = anon_map[visible_user_id]
        user_obj = {'object_type': 'user', 'name': visible_user_id}
        user_obj.update(user_dict)        
        user_obj['userdetailslink'] = \
                                    {'object_type': 'link',
                                     'destination':
                                     'viewuser.py?cert_id=%s'\
                                     % quote(visible_user_id),
                                     'class': 'infolink',
                                     '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 = allow_vgrids
        else:
            email_vgrids = set(vgrids_allow_email).intersection(allow_vgrids)
        if any_vgrid in vgrids_allow_im:
            im_vgrids = allow_vgrids
        else:
            im_vgrids = set(vgrids_allow_im).intersection(allow_vgrids)
        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):
                js_name = 'send%s%s' % (proto, hexlify(visible_user_id))
                helper = html_post_helper(js_name, 'sendrequestaction.py',
                                          {'cert_id': visible_user_id,
                                           'request_type': 'plain',
                                           'protocol': proto,
                                           'request_text': ''})
                output_objects.append({'object_type': 'html_form', 'text':
                                       helper})
                link = 'send%slink' % proto
                user_obj[link] = {'object_type': 'link',
                                  'destination':
                                  "javascript: confirmDialog(%s, '%s', '%s');"\
                                  % (js_name, 'Really send %s message to %s?'\
                                     % (proto, visible_user_id),
                                     'request_text'),
                                  'class': link,
                                  'title': 'Send %s message to %s' % \
                                  (proto, visible_user_id), 
                                  'text': ''}
        users.append(user_obj)

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

    return (output_objects, returnvalues.OK)
コード例 #24
0
ファイル: settings.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    client_dir = client_id_dir(client_id)
    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()
コード例 #25
0
ファイル: migadmin.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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
    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" 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. 9 (created)
          var sortOrder = [[9,0]];

          $("#certreqtable").tablesorter({widgets: ["zebra", "saveSort"],
                                        sortList:sortOrder
                                        })
                               .tablesorterPager({ container: $("#pager"),
                                        size: %s
                                        });
     }
);
</script>
''' % default_pager_entries

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s administration panel' % configuration.short_title
    title_entry['meta'] = meta
    title_entry['style'] = style
    title_entry['javascript'] = 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>
'''                       })

    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() + certreq_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 certreq_actions:
        if action == "addcertreq":
            for req_id in req_list:
                if accept_cert_req(req_id, configuration):
                    output_objects.append(
                        {'object_type': 'text', 'text':
                         'Accepted certificate request %s' % req_id})
                else:
                    output_objects.append(
                        {'object_type': 'error_text', 'text':
                         'Accept certificate request failed - details in log'
                         })
        elif action == "delcertreq":
            for req_id in req_list:
                if delete_cert_req(req_id, configuration):
                    output_objects.append(
                        {'object_type': 'text', 'text':
                         'Deleted certificate request %s' % req_id})
                else:
                    output_objects.append(
                        {'object_type': 'error_text', 'text':
                         'Delete certificate request failed - details in log'
                         })

    show, drop = '', ''
    general = """
<h1>Server Status</h1>
<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 = ['grid_script.py', 'grid_monitor.py', 'grid_sshmux.py']
    # No need to run im_notify unless any im notify protocols are enabled
    if [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')
    for proc in daemon_names:
        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'})

    (status, ret) = list_cert_reqs(configuration)
    if not 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)

    certreqs = []
    for req_id in ret:
        (load_status, req_dict) = get_cert_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_certreqitem_object(configuration, req_dict)
        
        js_name = 'create%s' % req_id
        helper = html_post_helper(js_name, 'migadmin.py',
                                  {'action': 'addcertreq', 'req_id': req_id})
        output_objects.append({'object_type': 'html_form', 'text': helper})
        req_item['addcertreqlink'] = {
            'object_type': 'link', 'destination':
            "javascript: confirmDialog(%s, '%s');" % \
            (js_name, 'Really accept %s?' % req_id),
            'class': 'addlink', 'title': 'Accept %s' % req_id, 'text': ''}
        js_name = 'delete%s' % req_id
        helper = html_post_helper(js_name, 'migadmin.py',
                                  {'action': 'delcertreq', 'req_id': req_id})
        output_objects.append({'object_type': 'html_form', 'text': helper})
        req_item['delcertreqlink'] = {
            'object_type': 'link', 'destination':
            "javascript: confirmDialog(%s, '%s');" % \
            (js_name, 'Really remove %s?' % req_id),
            'class': 'removelink', 'title': 'Remove %s' % req_id, 'text': ''}
        certreqs.append(req_item)

    output_objects.append({'object_type': 'table_pager', 'entry_name':
                           'pending certificate requests',
                           'default_entries': default_pager_entries})
    output_objects.append({'object_type': 'certreqs',
                          'certreqs': certreqs})

    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 += '''
<h1>%s</h1>
<textarea rows=%s cols=200 readonly="readonly">
''' % (log_path, lines)
        try:
            logger.debug("loading %d lines from %s" % (lines, log_path))
            log_fd = open(log_path, 'r')
            log_fd.seek(0, os.SEEK_END)
            size = log_fd.tell()
            pos = log_fd.tell()
            log_lines = []
            step_size = 100
            # locate last X lines 
            while pos > 0 and len(log_lines) < lines:
                offset = min(lines * step_size, size)
                logger.debug("seek to offset %d from end of %s" % (offset,
                                                                  log_path))
                log_fd.seek(-offset, os.SEEK_END)
                pos = log_fd.tell()
                log_lines = log_fd.readlines()
                step_size *= 2
            logger.debug("reading %d lines from %s" % (lines, log_path))
            html += ''.join(log_lines[-lines:])
            log_fd.close()
        except Exception, exc:
            logger.error("reading %d lines from %s: %s" % (lines, log_path,
                                                           exc))
            output_objects.append({'object_type': 'error_text', 'text'
                                   : 'Error reading log (%s)' % exc})
            return (output_objects, returnvalues.SYSTEM_ERROR)
        html += '''</textarea>
コード例 #26
0
ファイル: reqcert.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False, 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)
コード例 #27
0
ファイル: showvgridmonitor.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = initialize_main_variables(client_id, op_header=False)
    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})
コード例 #28
0
ファイル: adminvgrid.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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)
コード例 #29
0
ファイル: extcert.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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)
コード例 #30
0
ファイル: adminfreeze.py プロジェクト: ucphhpc/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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()
    freeze_id = accepted['freeze_id'][-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 site admins %s if you think it should be enabled.
''' % configuration.admin_email
        })
        return (output_objects, returnvalues.OK)

    # Load existing freeze for stepwise construction if requested
    freeze_dict = {'ID': freeze_id, 'FLAVOR': flavor}
    if freeze_id != keyword_auto:
        (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, brief_freeze(freeze_dict)))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Could not read details for "%s"' % freeze_id
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)

        logger.debug("%s: loaded freeze: %s" %
                     (op_name, brief_freeze(freeze_dict)))

        # Preserve already saved flavor
        flavor = freeze_dict.get('FLAVOR', 'freeze')

        freeze_state = freeze_dict.get('STATE', keyword_final)
        if freeze_state == keyword_final:
            logger.error("%s tried to edit finalized %s archive %s" %
                         (client_id, flavor, freeze_id))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You cannot edit finalized %s archive %s' % (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 freeze_state == keyword_updating:
            logger.error("%s tried to edit %s archive %s under update" %
                         (client_id, flavor, freeze_id))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You cannot edit %s archive %s until active update completes' %
                (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)

    form_method = 'post'
    csrf_limit = get_csrf_limit(configuration)
    fill_helpers = {
        'flavor': flavor,
        'form_method': form_method,
        'csrf_field': csrf_field,
        'csrf_limit': csrf_limit
    }
    target_op = 'uploadchunked'
    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})
    lookup_map = {
        'freeze_id': 'ID',
        'freeze_name': 'NAME',
        'freeze_author': 'AUTHOR',
        'freeze_description': 'DESCRIPTION'
    }
    for (key, val) in lookup_map.items():
        fill_helpers[key] = freeze_dict.get(val, '')
    fill_helpers['publish_value'] = 'no'
    if freeze_dict.get('PUBLISH', False):
        fill_helpers['publish_value'] = 'yes'

    # jquery fancy upload

    (add_import, add_init, add_ready) = fancy_upload_js(configuration,
                                                        csrf_token=csrf_token)

    # We need filechooser deps and dynamic addition of copy/upload fields

    add_import += '''
<script type="text/javascript" src="/images/js/jquery.tablesorter.js"></script>
<script type="text/javascript" src="/images/js/jquery.prettyprint.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>
<!-- The nouislider plugin used by the preview image plugin -->
<script type="text/javascript" src="/images/lib/noUiSlider/jquery.nouislider.all.js"></script>
    '''
    add_init += '''
Caman.DEBUG = false

var copy_fields = 0;
var upload_fields = 0;
var open_file_chooser;
var open_upload_dialog;
/* default upload destination */
var remote_path = "%s";
var trash_linkname = "%s";
var copy_div_id = "copyfiles";
var upload_div_id = "uploadfiles";
/* for upload_callback */
var field_id, field_name, wrap_id, upload_path, on_remove;

function add_copy() {
    var div_id = 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 upload_callback() {
    var div_id = upload_div_id;
    console.log("in upload callback");
    $(".uploadfileslist > tr > td > p.name > a").each(
        function(index) {
            console.log("callback for upload item no. "+index);
            upload_path = $(this).text();
            if ($(this).attr("href") == "") {
                console.log("skipping empty (error) upload: "+upload_path);
                // Continue to next iteration on errors
                return true;
            }
            console.log("callback for upload path "+upload_path);
            field_id = "freeze_move_"+upload_fields;
            field_name = "freeze_move_"+upload_fields;
            wrap_id = field_id+"_wrap";
            if ($("#"+div_id+" > span > input[value=\\""+upload_path+"\\"]").length) {
                console.log("skipping duplicate path: "+upload_path);
                // Continue to next iteration on errors
                return true;
            } else {
                console.log("adding new path: "+upload_path);
            }
            on_remove = "";
            on_remove += "remove_field("+wrap_id+");";
            on_remove += "$.fn.delete_upload(\\""+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=\\""+upload_path+"\\" /><br / >";
            upload_entry += "</span>";
            $("#"+div_id).append(upload_entry);
            console.log("callback added upload: "+upload_entry);
            upload_fields += 1;
        });
    console.log("callback done");
}

function add_upload() {
    openFancyUpload("Upload Files", upload_callback, "", remote_path, true,
                    "", "%s");
}

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

// init file chooser dialogs with directory selection support
function init_dialogs() {
    open_file_chooser = mig_filechooser_init("fm_filechooser",
        function(file) {
            return;
        }, false, "/");
    /* We reuse shared init function but use custom actual opener above
    to mangle resulting files into archive form. */
    initFancyUpload();
    /* Alias open_dialog to open_upload_dialog for clarity */
    open_upload_dialog = open_dialog;

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

function init_page() {
    init_dialogs();
}

    ''' % (upload_tmp_dir, trash_linkname, csrf_token)
    add_ready += '''
         // do sequenced initialisation (separate function)
         init_page();
    '''

    # TODO: can we update style inline to avoid explicit themed_styles?
    title_entry['style'] = themed_styles(
        configuration,
        base=[
            'jquery.contextmenu.css', 'jquery.managers.contextmenu.css',
            'jquery.xbreadcrumbs.css', 'jquery.fmbreadcrumbs.css',
            'jquery.fileupload.css', 'jquery.fileupload-ui.css'
        ],
        skin=['fileupload-ui.custom.css', 'xbreadcrumbs.custom.css'],
        user_settings=title_entry.get('user_settings', {}))
    title_entry['script']['advanced'] += add_import
    title_entry['script']['init'] += add_init
    title_entry['script']['ready'] += add_ready

    if flavor == 'freeze':
        fill_helpers['freeze_name'] = fill_helpers.get('freeze_name', '')
        fill_helpers["archive_header"] = "Freeze Archive Files"
        fill_helpers["button_label"] = "Save and Preview"
        intro_text = """
Please enter your archive details below and select any files to be included in
the archive.
"""
    elif flavor == 'phd':
        fill_helpers['freeze_name'] = fill_helpers.get('freeze_name', '')
        fill_helpers[
            "archive_header"] = "Thesis and Associated Files to Archive"
        fill_helpers["button_label"] = "Save and Preview"
        intro_text = """
Please enter your PhD details below and select any files associated with your
thesis.
"""
    elif flavor == 'backup':
        fill_helpers['freeze_name'] = fill_helpers.get('freeze_name', '')
        if not fill_helpers['freeze_name']:
            now = datetime.datetime.now().isoformat().replace(':', '')
            fill_helpers['freeze_name'] = 'backup-%s' % now
        fill_helpers["archive_header"] = "Files and folders to Archive"
        fill_helpers["button_label"] = "Save and Preview"
        intro_text = """
Please select the files and folders to backup below.
"""
    else:
        output_objects.append({
            'object_type': 'error_text',
            'text': "unknown flavor: %s" % flavor
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # Only warn here if default state is final and persistent
    if freeze_flavors[flavor]['states'][0] == keyword_final and \
            flavor in configuration.site_permanent_freeze:
        intro_text += """
<p class='warn_message'>Note that frozen archives <em>cannot</em> be changed
after final creation and then they can only be manually removed by management,
so please be careful when filling in the details.
</p>
"""

    fill_helpers["fancy_dialog"] = fancy_upload_html(configuration)

    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='tree-container container-fluid'>
        <div class='tree-row row'>
            <div class='tree-header col-3'></div>
            <div class='fm_path_breadcrumbs col-6'>
                <ul id='fm_xbreadcrumbs' class='xbreadcrumbs'><!-- dynamic --></ul>
            </div>
            <div class='fm_buttonbar col-3 d-none d-lg-block'>
                <ul id='fm_buttons' class='buttonbar'>
                    <!-- dynamically modified by js to show optional buttons -->
                    <li class='datatransfersbutton hidden' title='Manage Data Transfers'>&nbsp;</li>
                    <li class='sharelinksbutton hidden' title='Manage Share Links'>&nbsp;</li>
                    <li class='parentdirbutton' title='Open Parent Directory'>&nbsp;</li>
                    <li class='refreshbutton' title='Refresh'>&nbsp;</li>
                </ul>
            </div>
            <div class='fm_buttonbar-big col-6 d-block d-lg-none hidden'>
                <ul id='fm_buttons' class='buttonbar'>
                    <!-- dynamically modified by js to show optional buttons -->
                    <li class='datatransfersbutton hidden' title='Manage Data Transfers'>&nbsp;</li>
                    <li class='sharelinksbutton hidden' title='Manage Share Links'>&nbsp;</li>
                    <li class='parentdirbutton' title='Open Parent Directory'>&nbsp;</li>
                    <li class='refreshbutton' title='Refresh'>&nbsp;</li>
                </ul>
            </div>
        </div>
    </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 class='fm_name'>Name</th>
                    <th class='fm_size'>Size</th>
                    <th class='fm_type'>Type</th>
                    <th class='fm_date'>Date Modified</th>
                    <th class='fm_toolbox'>...</th>
                </tr>
            </thead>
            <tbody>
                <!-- this is a placeholder for contents: do not remove! -->
            </tbody>
         </table>
    </div>
    <div id='fm_statusbar' class='col-lg-12'>
        <div id='fm_statusprogress' class=' col-lg-3'>
            <div class='progress-label'>Loading...</div>
        </div>
        <div id='fm_statusinfo' class='col-lg-9'>&nbsp;</div>
    </div>
</div>
<div id='cmd_dialog' title='Command output' style='display: none;'></div>

%(fancy_dialog)s
    """ % fill_helpers

    target_op = 'createfreeze'
    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})

    freeze_form = """
<form enctype='multipart/form-data' method='%(form_method)s' action='%(target_op)s.py'>
<input type='hidden' name='%(csrf_field)s' value='%(csrf_token)s' />
<input type='hidden' name='flavor' value='%(flavor)s' />
<input type='hidden' name='freeze_id' value='%(freeze_id)s' />
<b>Name:</b><br />
<input class='fillwidth padspace' type='text' name='freeze_name'
    value='%(freeze_name)s' autofocus required pattern='[a-zA-Z0-9_. -]+'
    title='unique name for the freeze archive. I.e. letters and digits separated only by spaces, underscores, periods and hyphens' />
"""
    if flavor != 'backup':
        # TODO: do these make sense to have here or just forced in backend?
        freeze_form += """
<input type='hidden' name='freeze_department' value='' />
<input type='hidden' name='freeze_organization' value='' />
<br><b>Author(s):</b><br />
<input class='fillwidth padspace' type='text' name='freeze_author'
    value='%(freeze_author)s' title='optional archive author(s) in case archive is created on behalf of one or more people' />
<br /><b>Description:</b><br />
<textarea class='fillwidth padspace' rows='20' name='freeze_description'>%(freeze_description)s</textarea>
<br />
"""
    freeze_form += """
<br />
<div id='freezefiles'>
<b>%(archive_header)s:</b><br/>
"""
    freeze_form += """
<input type='button' id='addfilebutton' value='Add file/directory' />
"""
    if flavor != 'backup':
        freeze_form += """
<input type='button' id='adduploadbutton' value='Add upload' />
"""
    freeze_form += """
<div id='copyfiles'>
<!-- Dynamically filled -->
</div>
"""
    if flavor != 'backup':
        freeze_form += """
<div id='uploadfiles'>
<!-- Dynamically filled -->
</div>
"""
    freeze_form += """
</div>
<br />
"""
    if flavor != 'backup':
        freeze_form += """
<div id='freezepublish'>
<b>Make Dataset Publicly Available</b>
"""
        for val in ('yes', 'no'):
            checked = ''
            if fill_helpers['publish_value'] == val:
                checked = 'checked="checked"'
            freeze_form += """
<input type='radio' name='freeze_publish' value='%s' %s />%s
""" % (val, checked, val)
        freeze_form += """
</div>
<br />
"""
    freeze_form += """
<input type='submit' value='%(button_label)s' />
</form>
"""

    # TODO: consider in-lining showfreeze file table for direct modify instead
    #       probably requires more AJAX handling of actions.

    # for rel_path in frozen_files:
    #    freeze_form += """%s<br/>""" % rel_path

    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 % fill_helpers
    })

    # Link to view if archive already exists
    if freeze_id != keyword_auto:
        frozen_files = [
            i['name'] for i in freeze_dict.get('FILES', [])
            if i['name'] != public_archive_index
        ]
        # Info about contents and spacing before view button otherwise
        if frozen_files:
            output_objects.append({
                'object_type':
                'html_form',
                'text':
                """
<h3>Previously Added Files</h3>
<p>There are already %d file(s) saved in the archive and you can view and
manage those through the link below e.g. in case you change your mind
about including any of them.
</p>""" % len(frozen_files)
            })
        else:
            output_objects.append({'object_type': 'text', 'text': ''})

        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',
            'target':
            '_blank',
        })

    # Spacing
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
            <div class="vertical-spacer"></div>
    '''
    })

    return (output_objects, returnvalues.OK)
コード例 #31
0
ファイル: adminfreeze.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    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)
コード例 #32
0
ファイル: jobman.py プロジェクト: heromod/migrid
def css_tmpl(configuration):
    """Stylesheets to include in the page header"""
    css = themed_styles(configuration, base=['jquery.contextmenu.css'])
    return css
コード例 #33
0
ファイル: showfreeze.py プロジェクト: heromod/migrid
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = initialize_main_variables(client_id, op_header=False)
    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 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]["showfreeze_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 tablesorter

    css_helpers = {
        "css_base": os.path.join(configuration.site_images, "css"),
        "skin_base": configuration.site_skin_base,
    }
    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() {

          // table initially sorted by col. 0 (filename)
          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;
          }


          $("#frozenfilestable").tablesorter({widgets: ["zebra", "saveSort"],
                                        sortList:sortOrder,
                                        textExtraction: imgTitle
                                        })
                               .tablesorterPager({ container: $("#pager"),
                                        size: %s
                                        });
     }
);
</script>
"""
        % default_pager_entries
    )

    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": "'%s' is not an existing frozen archive!" % 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 details for "%s"' % freeze_id})
        return (output_objects, returnvalues.SYSTEM_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)

    output_objects.append(
        {"object_type": "table_pager", "entry_name": "frozen files", "default_entries": default_pager_entries}
    )
    output_objects.append(build_freezeitem_object(configuration, freeze_dict))

    return (output_objects, returnvalues.OK)