def getContent(req, ids): reload(su) language = lang(req) user = users.getUserFromRequest(req) username = user.getName() #access = acl.AccessData(user=user) access = acl.AccessData(req=req) if "schedule" in users.getHideMenusForUser(user): req.setStatus(httpstatus.HTTP_FORBIDDEN) return req.getTAL("web/edit/edit.html", {}, macro="access_error") errors = [] error = '' if "action" in req.params.keys(): action = req.params.get("action") if action.startswith("get_fields_for_"): schedule_func = req.params.get( "action").replace("get_fields_for_", "") fields = su.fc_dict[schedule_func].getMetafields(lang(req)) fieldDicts = su.fc_dict[schedule_func].getMetafieldDicts(lang(req)) field_errors = [] for i, field in enumerate(fields): field_errors.append(False) d = { 'fields': fields, 'fieldDicts': fieldDicts, 'currentField': fields[0], 'field_errors': field_errors, 'currentFunction': schedule_func, 'explain_func': su.fc_dict[schedule_func].getExplanation(language) } req.writeTAL("web/edit/modules/schedule.html", d, macro="schedule_func_show_fields_and_explanation") return "" elif action.startswith("load_schedule_"): schedule_id = action.replace("load_schedule_", "") try: schedule = tree.getNode(schedule_id) except: errors.append("edit_schedule_no_such_node_error") return "no such schedule error" if not schedule.type == "schedule" and access and access.hasWriteAccess(schedule): return "schedule access error" schedule_func = schedule.get("function") if schedule_func: fields = su.fc_dict[schedule_func].getMetafields(lang(req)) fieldDicts = su.fc_dict[ schedule_func].getMetafieldDicts(lang(req)) d['explain_func'] = su.fc_dict[ schedule_func].getExplanation(language) else: fields = [] fieldDicts = [] d['explain_func'] = "" field_errors = [] for i, field in enumerate(fields): field_errors.append(False) has_evaluation_errors = False for i, dfield in enumerate(fieldDicts): field_name = dfield['field_name'] field_value = schedule.get(field_name) dfield['value'] = field_value field_validator_func = dfield['field_validator_func'] if field_validator_func and not field_validator_func(field_value): dfield['evaluation_error'] = True has_evaluation_errors = True else: dfield['evaluation_error'] = False if has_evaluation_errors: error = "\n<br/>\n".join([error, t(language, 'edit_schedule_field_validation_error')]) d = { 'fields': fields, 'fieldDicts': fieldDicts, 'currentField': fields[0], 'field_errors': field_errors, 'currentFunction': schedule_func, } req.writeTAL("web/edit/modules/schedule.html", d, macro="schedule_func_show_fields_and_explanation") return "" elif action == "delete_node_from_schedule": node_id = req.params.get('node_id', None) if node_id: pass else: errors.append("edit_schedule_unexpected_no_such_node") schedule_id = req.params.get('schedule_id', None) if schedule_id: try: schedule = tree.getNode(schedule_id) except: errors.append( "edit_schedule_unexpected_no_such_schedule_node") else: errors.append("edit_schedule_unexpected_no_such_schedule_node") delete_errors = su.deleteNodeIDsFromSchedule( [node_id], schedule_id, access=access) if not delete_errors: msg = "user '%s' removed node %s from schedule '%s' (%s)" % ( username, node_id, schedule.name, schedule_id) logging.getLogger("backend").info(msg) else: error_msg = ", ".join([t(language, e) for e in delete_errors]) msg = "user '%s' tried to remove node %s from schedule '%s' (%s): %s" % ( username, node_id, schedule.name, schedule_id, error_msg) logging.getLogger("backend").error(msg) errors += delete_errors s = {} s['errors'] = errors s['delete_errors'] = delete_errors s['delete_table_rows'] = ['sid_%s' % schedule_id] res_msg = req.params.get( "jsoncallback") + "(%s)" % json.dumps(s, indent=4) req.write(res_msg) return "" elif action == "delete_schedule": schedule_id = req.params.get('schedule_id', None) if schedule_id: try: schedule = tree.getNode(schedule_id) except: errors.append( "edit_schedule_unexpected_no_such_schedule_node") else: errors.append("edit_schedule_unexpected_no_such_schedule_node") delete_errors = su.deleteSchedule(schedule_id, access=access) if not delete_errors: msg = "user '%s' removed schedule %s (%s)" % ( username, schedule.name, schedule_id) logging.getLogger("backend").info(msg) else: error_msg = ", ".join([t(language, e) for e in delete_errors]) msg = "user '%s' tried to remove schedule '%s' (%s): %s" % ( username, schedule.name, schedule_id, error_msg) logging.getLogger("backend").error(msg) errors += delete_errors s = {} s['errors'] = errors s['delete_errors'] = delete_errors s['delete_table_rows'] = ['sid_%s' % schedule_id] res_msg = req.params.get( "jsoncallback") + "(%s)" % json.dumps(s, indent=4) req.write(res_msg) return "" elif action == "load_table_nid2schedules": nid2schedules, schedule2nids, nid2active_schedules = su.getSchedulesForIds( ids, access=access, language=language) nid2schedules_attrs = {} for nid in nid2schedules: nid2schedules_attrs[nid] = [ [s.id, s.name, s.get("single_trigger")] for s in nid2schedules[nid]['schedule_list']] d = {} d['nid2schedules'] = nid2schedules d['nid2active_schedules'] = nid2active_schedules d['errors'] = ['testerror1', 'testerror1'] d['date'] = datetime.now().isoformat() d['isActive'] = su.isActive req.writeTAL( "web/edit/modules/schedule.html", d, macro="table_nid2schedules") return "" elif action == "load_table_schedule2nids": nid2schedules, schedule2nids, nid2active_schedules = su.getSchedulesForIds( ids, access=access, language=language) nid2schedules_attrs = {} for nid in nid2schedules: nid2schedules_attrs[nid] = [ [s.id, s.name, s.get("single_trigger")] for s in nid2schedules[nid]['schedule_list']] d = {} d['nid2schedules'] = nid2schedules d['schedule2nids'] = schedule2nids d['nid2active_schedules'] = nid2active_schedules d['errors'] = ['testerror1', 'testerror1'] d['date'] = datetime.now().isoformat() d['isActive'] = su.isActive req.writeTAL( "web/edit/modules/schedule.html", d, macro="table_schedule2nids") return "" nid2schedules, schedule2nids, nid2active_schedules = su.getSchedulesForIds( ids, access=access, language=language) datetime_str = req.params.get("datetime", "").strip() datetime_error = False has_evaluation_errors = False if datetime_str: patter = "^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$" if not re.match(patter, datetime_str): error = t( language, "edit_schedule_input_datetime_format_error") % datetime_str datetime_error = True else: try: parser_test_result = datetime.strptime( datetime_str, "%Y-%m-%dT%H:%M") # "%Y-%m-%dT%H:%M:%S.%f" except: parser_test_result = None error = t( language, "edit_schedule_input_datetime_format_error") % datetime_str datetime_error = True if parser_test_result and datetime_str <= datetime.now().isoformat(): error = t( language, "edit_schedule_input_datetime_already_past_error") % datetime_str datetime_error = True elif "submit" in req.params: error = t( language, "edit_schedule_input_datetime_format_error") % datetime_str datetime_error = True schedule_id = req.params.get("schedule_id", "") if schedule_id: schedule = tree.getNode(schedule_id) if access and not access.hasWriteAccess(schedule): errors.append("edit_schedule_no_access_error") schedule = None current_function = req.params.get('schedule_function', '') else: current_function = schedule.get("function") else: schedule = None current_function = req.params.get('schedule_function', '') if "submit" in req.params or "submit_run_now" in req.params: current_function = req.params.get('schedule_function', '') if current_function in su.fc_dict: field_descriptors = su.fc_dict[ current_function].getFieldDescriptors() field_errors = [] else: # should not happen msg = "-> unexpected error: 'non-existant schedule function' requested in module %s: :s" % ( str(__file__), str(inspect.currentframe().f_lineno)) print msg logging.getLogger("backend").error(msg) d = { "id": req.params.get("id") } # nodes list is used to display icons in upper part of page # additional nodes should not / will not be shown there nodes = [] for nid in ids: node = tree.getNode(nid) nodes.append(node) d['nodes'] = nodes if current_function in su.fc_dict: fields = su.fc_dict[current_function].getMetafields(lang(req)) fieldDicts = su.fc_dict[current_function].getMetafieldDicts(lang(req)) d['explain_func'] = su.fc_dict[ current_function].getExplanation(language) else: fields = [] fieldDicts = [] d['explain_func'] = "" if not "submit_run_now" in req.params: has_evaluation_errors = datetime_error if schedule and not "submit" in req.params and not "submit_run_now" in req.params: for i, dfield in enumerate(fieldDicts): field_name = dfield['field_name'] field_value = schedule.get(field_name) dfield['value'] = field_value field_validator_func = dfield['field_validator_func'] if field_validator_func and not field_validator_func(field_value): dfield['evaluation_error'] = True has_evaluation_errors = True else: dfield['evaluation_error'] = False else: for i, dfield in enumerate(fieldDicts): field_name = dfield['field_name'] # m_* classes from metadata/ are not multilingual for schedules # their getEditorHTML methods are used to display schedule node # attributes field_value = req.params.get( getDefaultLanguage() + '__' + field_name, '') dfield['value'] = field_value field_validator_func = dfield['field_validator_func'] if field_validator_func and not field_validator_func(field_value): dfield['evaluation_error'] = True has_evaluation_errors = True else: dfield['evaluation_error'] = False additional_nodes_str = req.params.get("additional_nodes", "") additional_nodes_error = False additional_nodes_bad_ids = [] try: additional_nodes_id_list = [ str(int(nid.strip())) for nid in additional_nodes_str.strip().split(";") if nid.strip()] except: has_evaluation_errors = True additional_nodes_error = True additional_nodes_id_list = [] errors.append( "edit_schedule_additional_nodes_list_not_semikolon_separated_list_of_integers") if not additional_nodes_error: collections_root = tree.getRoot("collections") for nid in additional_nodes_id_list: n = None try: n = tree.getNode(nid) except tree.NoSuchNodeError as e: has_evaluation_errors = True additional_nodes_error = True if nid not in additional_nodes_bad_ids: additional_nodes_bad_ids.append(nid) if n and (not isDescendantOf(n, collections_root) or not access.hasWriteAccess(n)): # to do? discussion: override collections rectriction for # admins ? has_evaluation_errors = True additional_nodes_error = True if nid not in additional_nodes_bad_ids: additional_nodes_bad_ids.append(nid) if additional_nodes_bad_ids: has_evaluation_errors = True additional_nodes_error = True errors.append(t(language, "edit_schedule_additional_nodes_bad_ids") + (";".join(additional_nodes_bad_ids))) if has_evaluation_errors: errors.append('edit_schedule_field_validation_error') error = "\n<br/>\n".join(map(lambda x: t(language, x), [error] + errors)) d['fields'] = fields d['fieldDicts'] = fieldDicts d['field_errors'] = [False] * len(fields) d['currentField'] = None d['currentFunction'] = current_function d['error'] = error d['fc_dict'] = su.filter_access(su.fc_dict, access) d['input_datetime'] = datetime_str d['input_datetime_error'] = datetime_error d['nid2schedules'] = nid2schedules d['schedule2nids'] = schedule2nids d['nid2active_schedules'] = nid2active_schedules d['loaded_schedule'] = schedule if schedule: d['loaded_schedule_id'] = str(schedule.id) else: d['loaded_schedule_id'] = None d['mklink'] = su.mklink d['language'] = language d['t'] = t d['isActive'] = su.isActive d['result'] = '' d['created_new_schedule'] = False d['additional_nodes'] = additional_nodes_str d['additional_nodes_error'] = additional_nodes_error d['submitbutton_run_now_label'] = t( language, 'edit_schedule_submit_run_now_button') d['edit_schedule_submit_run_now_button_confirm'] = t( language, 'edit_schedule_submit_run_now_button_confirm') d['edit_schedule_delete_schedule_confirm'] = t( language, 'edit_schedule_delete_schedule_confirm') if has_evaluation_errors and not ('submit_run_now' in req.params): return req.getTAL("web/edit/modules/schedule.html", d, macro="schedule_popup") new_schedule = None if (not schedule and "submit" in req.params) or "submit_run_now" in req.params: new_schedule_name = user.name + \ "_created_at_" + datetime.now().isoformat() new_schedule = tree.Node(new_schedule_name, 'schedule') username = user.getName() new_schedule.setAccess("write", "{user %s}" % username) if not "submit_run_now" in req.params: schedules = tree.getRoot("schedules") schedules.addChild(new_schedule) msg = "user '%s' created new schedule '%s' (%s), trigger='%s', function='%s', nodelist='%s'" % ( username, new_schedule.name, str(new_schedule.id), datetime_str, d['currentFunction'], new_schedule.get('nodelist')) logging.getLogger("backend").info(msg) d['result'] = t( language, 'edit_schedule_result_new_schedule_created') d['created_new_schedule'] = True else: msg = "user '%s' created temporary schedule '%s' (%s), trigger='%s', function='%s', nodelist='%s'" % ( username, new_schedule.name, str(new_schedule.id), datetime_str, d['currentFunction'], new_schedule.get('nodelist')) logging.getLogger("backend").info(msg) d['result'] = t( language, 'edit_schedule_result_temporary_schedule_created') d['created_temporary_schedule'] = True elif (schedule) and ("submit" in req.params): new_schedule = schedule msg = "user '%s' is editing schedule '%s' (%s), trigger='%s', function='%s', nodelist='%s'" % ( username, new_schedule.name, str(new_schedule.id), datetime_str, d['currentFunction'], new_schedule.get('nodelist')) logging.getLogger("backend").info(msg) new_schedule.set("system.edited", datetime.now().isoformat()) d['result'] = t( language, 'edit_schedule_result_existing_schedule_edited') if new_schedule: for i, dfield in enumerate(fieldDicts): field_name = dfield['field_name'] field_value = dfield['value'] new_schedule.set(field_name, field_value) ids_plus_additional_nodes = ids for nid in additional_nodes_id_list: if nid not in ids_plus_additional_nodes: ids_plus_additional_nodes.append(nid) new_schedule.set('function', d['currentFunction']) new_schedule.set('nodelist', ",".join(ids_plus_additional_nodes)) new_schedule.set('single_trigger', datetime_str) if datetime.now().isoformat() < datetime_str: new_schedule.set('single_trigger_status', '') if "submit_run_now" in req.params: new_schedule.set("single_trigger", datetime.now().isoformat()) has_fired, has_error, TT = su.handle_single_trigger( new_schedule, datetime.now().isoformat(), su.OUT) if has_error: _error1 = d['error'] _error2 = "<br/>\n".join(map(lambda x: (t(language, str(x))), TT)) _error = "<br/>\n".join([_error1, _error2]) d['error'] = _error return req.getTAL("web/edit/modules/schedule.html", d, macro="schedule_popup")
def scheduler_thread(): global count import utils.scheduleutils as scheduleutils if not time: return ensureSchedulesRoot() TRIGGER_COUNT = 0 while True: count += 1 TT = [] HAS_FIRED = HAS_ERROR = False atime0 = atime = time.time() now_obj = datetime.now() now_str = now_obj.isoformat() # example: '2012-05-29T13:15:17.557000' if athana.ATHANA_STARTED: if count % scheduleutils.TRIGGER_INTERVAL == 0: TRIGGER_COUNT += 1 sched_root = tree.getRoot("schedules") try: tree.remove_from_nodecaches(sched_root) msg = "flushed schedules" TT.append([msg, time.time() - atime]) atime = time.time() except TypeError: msg = "scheduler thread failed to remove schedules root from cache" OUT(msg, logger='backend', level='warning') sched_list = [ c for c in sched_root.getChildren() if c.type == 'schedule' ] # to do: sort? msg = "%d schedule(s) found" % len(sched_list) TT.append([msg, time.time() - atime]) atime = time.time() SCHEDULES_IMPORT_ERROR = False try: reload(scheduleutils) msg = "reloaded module utils.scheduleutils" TT.append([msg, time.time() - atime]) atime = time.time() except: msg = "Error reloading module 'scheduleutils': %s %s" % ( str(sys.exc_info()[0]), str(sys.exc_info()[1])) TT.append([msg, time.time() - atime]) atime = time.time() OUT(msg, logger='backend', print_stdout=True, level='error') SCHEDULES_IMPORT_ERROR = True if not SCHEDULES_IMPORT_ERROR: interval_seconds = scheduleutils.SLEEP_INTERVAL * scheduleutils.TRIGGER_INTERVAL OUT("scheduler_thread (interval: %s sec.): %s" % (str(interval_seconds), now_str)) now_obj = datetime.now() now_str = now_obj.isoformat() for s in sched_list: has_fired, has_error, tt = scheduleutils.handle_single_trigger( s, now_str, OUT) TT = TT + tt atime = time.time() if has_fired: HAS_FIRED = True if has_error: HAS_ERROR = True try: has_fired, has_error, tt = scheduleutils.handle_cron_dict( s, now_obj, OUT) except: has_fired, has_error, tt = False, True, [] TT = TT + tt atime = time.time() if has_fired: HAS_FIRED = True if has_error: HAS_ERROR = True sys.stdout.flush() else: msg = 'scheduler: check no: %d: athana not yet started' % (count) OUT(msg, print_stdout=False) def OUT_TT(TT): msg = "scheduler: timetable (scheduleutils.DEBUG = '%s')\n|" % ( scheduleutils.DEBUG) + '-' * 60 + '\n' msg += '| check no %d at %s:\n' % (TRIGGER_COUNT, now_str) for s, t in TT: msg = msg + '| %.3f: %s\n' % (t, str(s)) msg += '| duration: %.3f sec.\n' % (time.time() - atime0) msg += '|' + '-' * 60 OUT(msg) if scheduleutils.DEBUG: if TT: OUT_TT(TT) else: if (HAS_FIRED or HAS_ERROR) and TT: OUT_TT(TT) correction = int((time.time() - atime0) / scheduleutils.SLEEP_INTERVAL) count += correction time.sleep(scheduleutils.SLEEP_INTERVAL)
def scheduler_thread(): global count import utils.scheduleutils as scheduleutils if not time: return ensureSchedulesRoot() TRIGGER_COUNT = 0 while True: count += 1 TT = [] HAS_FIRED = HAS_ERROR = False atime0 = atime = time.time() now_obj = datetime.now() now_str = now_obj.isoformat() # example: '2012-05-29T13:15:17.557000' if athana.ATHANA_STARTED: if count % scheduleutils.TRIGGER_INTERVAL == 0: TRIGGER_COUNT += 1 sched_root = tree.getRoot("schedules") try: tree.remove_from_nodecaches(sched_root) msg = "flushed schedules" TT.append([msg, time.time() - atime]) atime = time.time() except TypeError: msg = "scheduler thread failed to remove schedules root from cache" OUT(msg, logger='backend', level='warning') sched_list = [c for c in sched_root.getChildren() if c.type == 'schedule'] # to do: sort? msg = "%d schedule(s) found" % len(sched_list) TT.append([msg, time.time() - atime]) atime = time.time() SCHEDULES_IMPORT_ERROR = False try: reload(scheduleutils) msg = "reloaded module utils.scheduleutils" TT.append([msg, time.time() - atime]) atime = time.time() except: msg = "Error reloading module 'scheduleutils': %s %s" % (str(sys.exc_info()[0]), str(sys.exc_info()[1])) TT.append([msg, time.time() - atime]) atime = time.time() OUT(msg, logger='backend', print_stdout=True, level='error') SCHEDULES_IMPORT_ERROR = True if not SCHEDULES_IMPORT_ERROR: interval_seconds = scheduleutils.SLEEP_INTERVAL * scheduleutils.TRIGGER_INTERVAL OUT("scheduler_thread (interval: %s sec.): %s" % (str(interval_seconds), now_str)) now_obj = datetime.now() now_str = now_obj.isoformat() for s in sched_list: has_fired, has_error, tt = scheduleutils.handle_single_trigger(s, now_str, OUT) TT = TT + tt atime = time.time() if has_fired: HAS_FIRED = True if has_error: HAS_ERROR = True try: has_fired, has_error, tt = scheduleutils.handle_cron_dict(s, now_obj, OUT) except: has_fired, has_error, tt = False, True, [] TT = TT + tt atime = time.time() if has_fired: HAS_FIRED = True if has_error: HAS_ERROR = True sys.stdout.flush() else: msg = 'scheduler: check no: %d: athana not yet started' % (count) OUT(msg, print_stdout=False) def OUT_TT(TT): msg = "scheduler: timetable (scheduleutils.DEBUG = '%s')\n|" % (scheduleutils.DEBUG) + '-' * 60 + '\n' msg += '| check no %d at %s:\n' % (TRIGGER_COUNT, now_str) for s, t in TT: msg = msg + '| %.3f: %s\n' % (t, str(s)) msg += '| duration: %.3f sec.\n' % (time.time() - atime0) msg += '|' + '-' * 60 OUT(msg) if scheduleutils.DEBUG: if TT: OUT_TT(TT) else: if (HAS_FIRED or HAS_ERROR) and TT: OUT_TT(TT) correction = int((time.time() - atime0) / scheduleutils.SLEEP_INTERVAL) count += correction time.sleep(scheduleutils.SLEEP_INTERVAL)
def getContent(req, ids): reload(su) language = lang(req) user = users.getUserFromRequest(req) username = user.getName() #access = acl.AccessData(user=user) access = acl.AccessData(req=req) if "schedule" in users.getHideMenusForUser(user): req.setStatus(httpstatus.HTTP_FORBIDDEN) return req.getTAL("web/edit/edit.html", {}, macro="access_error") errors = [] error = '' if "action" in req.params.keys(): action = req.params.get("action") if action.startswith("get_fields_for_"): schedule_func = req.params.get("action").replace( "get_fields_for_", "") fields = su.fc_dict[schedule_func].getMetafields(lang(req)) fieldDicts = su.fc_dict[schedule_func].getMetafieldDicts(lang(req)) field_errors = [] for i, field in enumerate(fields): field_errors.append(False) d = { 'fields': fields, 'fieldDicts': fieldDicts, 'currentField': fields[0], 'field_errors': field_errors, 'currentFunction': schedule_func, 'explain_func': su.fc_dict[schedule_func].getExplanation(language) } req.writeTAL("web/edit/modules/schedule.html", d, macro="schedule_func_show_fields_and_explanation") return "" elif action.startswith("load_schedule_"): schedule_id = action.replace("load_schedule_", "") try: schedule = tree.getNode(schedule_id) except: errors.append("edit_schedule_no_such_node_error") return "no such schedule error" if not schedule.type == "schedule" and access and access.hasWriteAccess( schedule): return "schedule access error" schedule_func = schedule.get("function") if schedule_func: fields = su.fc_dict[schedule_func].getMetafields(lang(req)) fieldDicts = su.fc_dict[schedule_func].getMetafieldDicts( lang(req)) d['explain_func'] = su.fc_dict[schedule_func].getExplanation( language) else: fields = [] fieldDicts = [] d['explain_func'] = "" field_errors = [] for i, field in enumerate(fields): field_errors.append(False) has_evaluation_errors = False for i, dfield in enumerate(fieldDicts): field_name = dfield['field_name'] field_value = schedule.get(field_name) dfield['value'] = field_value field_validator_func = dfield['field_validator_func'] if field_validator_func and not field_validator_func( field_value): dfield['evaluation_error'] = True has_evaluation_errors = True else: dfield['evaluation_error'] = False if has_evaluation_errors: error = "\n<br/>\n".join([ error, t(language, 'edit_schedule_field_validation_error') ]) d = { 'fields': fields, 'fieldDicts': fieldDicts, 'currentField': fields[0], 'field_errors': field_errors, 'currentFunction': schedule_func, } req.writeTAL("web/edit/modules/schedule.html", d, macro="schedule_func_show_fields_and_explanation") return "" elif action == "delete_node_from_schedule": node_id = req.params.get('node_id', None) if node_id: pass else: errors.append("edit_schedule_unexpected_no_such_node") schedule_id = req.params.get('schedule_id', None) if schedule_id: try: schedule = tree.getNode(schedule_id) except: errors.append( "edit_schedule_unexpected_no_such_schedule_node") else: errors.append("edit_schedule_unexpected_no_such_schedule_node") delete_errors = su.deleteNodeIDsFromSchedule([node_id], schedule_id, access=access) if not delete_errors: msg = "user '%s' removed node %s from schedule '%s' (%s)" % ( username, node_id, schedule.name, schedule_id) logging.getLogger("backend").info(msg) else: error_msg = ", ".join([t(language, e) for e in delete_errors]) msg = "user '%s' tried to remove node %s from schedule '%s' (%s): %s" % ( username, node_id, schedule.name, schedule_id, error_msg) logging.getLogger("backend").error(msg) errors += delete_errors s = {} s['errors'] = errors s['delete_errors'] = delete_errors s['delete_table_rows'] = ['sid_%s' % schedule_id] res_msg = req.params.get("jsoncallback") + "(%s)" % json.dumps( s, indent=4) req.write(res_msg) return "" elif action == "delete_schedule": schedule_id = req.params.get('schedule_id', None) if schedule_id: try: schedule = tree.getNode(schedule_id) except: errors.append( "edit_schedule_unexpected_no_such_schedule_node") else: errors.append("edit_schedule_unexpected_no_such_schedule_node") delete_errors = su.deleteSchedule(schedule_id, access=access) if not delete_errors: msg = "user '%s' removed schedule %s (%s)" % ( username, schedule.name, schedule_id) logging.getLogger("backend").info(msg) else: error_msg = ", ".join([t(language, e) for e in delete_errors]) msg = "user '%s' tried to remove schedule '%s' (%s): %s" % ( username, schedule.name, schedule_id, error_msg) logging.getLogger("backend").error(msg) errors += delete_errors s = {} s['errors'] = errors s['delete_errors'] = delete_errors s['delete_table_rows'] = ['sid_%s' % schedule_id] res_msg = req.params.get("jsoncallback") + "(%s)" % json.dumps( s, indent=4) req.write(res_msg) return "" elif action == "load_table_nid2schedules": nid2schedules, schedule2nids, nid2active_schedules = su.getSchedulesForIds( ids, access=access, language=language) nid2schedules_attrs = {} for nid in nid2schedules: nid2schedules_attrs[nid] = [[ s.id, s.name, s.get("single_trigger") ] for s in nid2schedules[nid]['schedule_list']] d = {} d['nid2schedules'] = nid2schedules d['nid2active_schedules'] = nid2active_schedules d['errors'] = ['testerror1', 'testerror1'] d['date'] = datetime.now().isoformat() d['isActive'] = su.isActive req.writeTAL("web/edit/modules/schedule.html", d, macro="table_nid2schedules") return "" elif action == "load_table_schedule2nids": nid2schedules, schedule2nids, nid2active_schedules = su.getSchedulesForIds( ids, access=access, language=language) nid2schedules_attrs = {} for nid in nid2schedules: nid2schedules_attrs[nid] = [[ s.id, s.name, s.get("single_trigger") ] for s in nid2schedules[nid]['schedule_list']] d = {} d['nid2schedules'] = nid2schedules d['schedule2nids'] = schedule2nids d['nid2active_schedules'] = nid2active_schedules d['errors'] = ['testerror1', 'testerror1'] d['date'] = datetime.now().isoformat() d['isActive'] = su.isActive req.writeTAL("web/edit/modules/schedule.html", d, macro="table_schedule2nids") return "" nid2schedules, schedule2nids, nid2active_schedules = su.getSchedulesForIds( ids, access=access, language=language) datetime_str = req.params.get("datetime", "").strip() datetime_error = False has_evaluation_errors = False if datetime_str: patter = "^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$" if not re.match(patter, datetime_str): error = t( language, "edit_schedule_input_datetime_format_error") % datetime_str datetime_error = True else: try: parser_test_result = datetime.strptime( datetime_str, "%Y-%m-%dT%H:%M") # "%Y-%m-%dT%H:%M:%S.%f" except: parser_test_result = None error = t( language, "edit_schedule_input_datetime_format_error") % datetime_str datetime_error = True if parser_test_result and datetime_str <= datetime.now().isoformat( ): error = t(language, "edit_schedule_input_datetime_already_past_error" ) % datetime_str datetime_error = True elif "submit" in req.params: error = t(language, "edit_schedule_input_datetime_format_error") % datetime_str datetime_error = True schedule_id = req.params.get("schedule_id", "") if schedule_id: schedule = tree.getNode(schedule_id) if access and not access.hasWriteAccess(schedule): errors.append("edit_schedule_no_access_error") schedule = None current_function = req.params.get('schedule_function', '') else: current_function = schedule.get("function") else: schedule = None current_function = req.params.get('schedule_function', '') if "submit" in req.params or "submit_run_now" in req.params: current_function = req.params.get('schedule_function', '') if current_function in su.fc_dict: field_descriptors = su.fc_dict[ current_function].getFieldDescriptors() field_errors = [] else: # should not happen msg = "-> unexpected error: 'non-existant schedule function' requested in module %s: :s" % ( str(__file__), str(inspect.currentframe().f_lineno)) print msg logging.getLogger("backend").error(msg) d = {"id": req.params.get("id")} # nodes list is used to display icons in upper part of page # additional nodes should not / will not be shown there nodes = [] for nid in ids: node = tree.getNode(nid) nodes.append(node) d['nodes'] = nodes if current_function in su.fc_dict: fields = su.fc_dict[current_function].getMetafields(lang(req)) fieldDicts = su.fc_dict[current_function].getMetafieldDicts(lang(req)) d['explain_func'] = su.fc_dict[current_function].getExplanation( language) else: fields = [] fieldDicts = [] d['explain_func'] = "" if not "submit_run_now" in req.params: has_evaluation_errors = datetime_error if schedule and not "submit" in req.params and not "submit_run_now" in req.params: for i, dfield in enumerate(fieldDicts): field_name = dfield['field_name'] field_value = schedule.get(field_name) dfield['value'] = field_value field_validator_func = dfield['field_validator_func'] if field_validator_func and not field_validator_func(field_value): dfield['evaluation_error'] = True has_evaluation_errors = True else: dfield['evaluation_error'] = False else: for i, dfield in enumerate(fieldDicts): field_name = dfield['field_name'] # m_* classes from metadata/ are not multilingual for schedules # their getEditorHTML methods are used to display schedule node # attributes field_value = req.params.get( getDefaultLanguage() + '__' + field_name, '') dfield['value'] = field_value field_validator_func = dfield['field_validator_func'] if field_validator_func and not field_validator_func(field_value): dfield['evaluation_error'] = True has_evaluation_errors = True else: dfield['evaluation_error'] = False additional_nodes_str = req.params.get("additional_nodes", "") additional_nodes_error = False additional_nodes_bad_ids = [] try: additional_nodes_id_list = [ str(int(nid.strip())) for nid in additional_nodes_str.strip().split(";") if nid.strip() ] except: has_evaluation_errors = True additional_nodes_error = True additional_nodes_id_list = [] errors.append( "edit_schedule_additional_nodes_list_not_semikolon_separated_list_of_integers" ) if not additional_nodes_error: collections_root = tree.getRoot("collections") for nid in additional_nodes_id_list: n = None try: n = tree.getNode(nid) except tree.NoSuchNodeError as e: has_evaluation_errors = True additional_nodes_error = True if nid not in additional_nodes_bad_ids: additional_nodes_bad_ids.append(nid) if n and (not isDescendantOf(n, collections_root) or not access.hasWriteAccess(n)): # to do? discussion: override collections rectriction for # admins ? has_evaluation_errors = True additional_nodes_error = True if nid not in additional_nodes_bad_ids: additional_nodes_bad_ids.append(nid) if additional_nodes_bad_ids: has_evaluation_errors = True additional_nodes_error = True errors.append( t(language, "edit_schedule_additional_nodes_bad_ids") + (";".join(additional_nodes_bad_ids))) if has_evaluation_errors: errors.append('edit_schedule_field_validation_error') error = "\n<br/>\n".join( map(lambda x: t(language, x), [error] + errors)) d['fields'] = fields d['fieldDicts'] = fieldDicts d['field_errors'] = [False] * len(fields) d['currentField'] = None d['currentFunction'] = current_function d['error'] = error d['fc_dict'] = su.filter_access(su.fc_dict, access) d['input_datetime'] = datetime_str d['input_datetime_error'] = datetime_error d['nid2schedules'] = nid2schedules d['schedule2nids'] = schedule2nids d['nid2active_schedules'] = nid2active_schedules d['loaded_schedule'] = schedule if schedule: d['loaded_schedule_id'] = str(schedule.id) else: d['loaded_schedule_id'] = None d['mklink'] = su.mklink d['language'] = language d['t'] = t d['isActive'] = su.isActive d['result'] = '' d['created_new_schedule'] = False d['additional_nodes'] = additional_nodes_str d['additional_nodes_error'] = additional_nodes_error d['submitbutton_run_now_label'] = t(language, 'edit_schedule_submit_run_now_button') d['edit_schedule_submit_run_now_button_confirm'] = t( language, 'edit_schedule_submit_run_now_button_confirm') d['edit_schedule_delete_schedule_confirm'] = t( language, 'edit_schedule_delete_schedule_confirm') if has_evaluation_errors and not ('submit_run_now' in req.params): return req.getTAL("web/edit/modules/schedule.html", d, macro="schedule_popup") new_schedule = None if (not schedule and "submit" in req.params) or "submit_run_now" in req.params: new_schedule_name = user.name + \ "_created_at_" + datetime.now().isoformat() new_schedule = tree.Node(new_schedule_name, 'schedule') username = user.getName() new_schedule.setAccess("write", "{user %s}" % username) if not "submit_run_now" in req.params: schedules = tree.getRoot("schedules") schedules.addChild(new_schedule) msg = "user '%s' created new schedule '%s' (%s), trigger='%s', function='%s', nodelist='%s'" % ( username, new_schedule.name, str( new_schedule.id), datetime_str, d['currentFunction'], new_schedule.get('nodelist')) logging.getLogger("backend").info(msg) d['result'] = t(language, 'edit_schedule_result_new_schedule_created') d['created_new_schedule'] = True else: msg = "user '%s' created temporary schedule '%s' (%s), trigger='%s', function='%s', nodelist='%s'" % ( username, new_schedule.name, str( new_schedule.id), datetime_str, d['currentFunction'], new_schedule.get('nodelist')) logging.getLogger("backend").info(msg) d['result'] = t(language, 'edit_schedule_result_temporary_schedule_created') d['created_temporary_schedule'] = True elif (schedule) and ("submit" in req.params): new_schedule = schedule msg = "user '%s' is editing schedule '%s' (%s), trigger='%s', function='%s', nodelist='%s'" % ( username, new_schedule.name, str(new_schedule.id), datetime_str, d['currentFunction'], new_schedule.get('nodelist')) logging.getLogger("backend").info(msg) new_schedule.set("system.edited", datetime.now().isoformat()) d['result'] = t(language, 'edit_schedule_result_existing_schedule_edited') if new_schedule: for i, dfield in enumerate(fieldDicts): field_name = dfield['field_name'] field_value = dfield['value'] new_schedule.set(field_name, field_value) ids_plus_additional_nodes = ids for nid in additional_nodes_id_list: if nid not in ids_plus_additional_nodes: ids_plus_additional_nodes.append(nid) new_schedule.set('function', d['currentFunction']) new_schedule.set('nodelist', ",".join(ids_plus_additional_nodes)) new_schedule.set('single_trigger', datetime_str) if datetime.now().isoformat() < datetime_str: new_schedule.set('single_trigger_status', '') if "submit_run_now" in req.params: new_schedule.set("single_trigger", datetime.now().isoformat()) has_fired, has_error, TT = su.handle_single_trigger( new_schedule, datetime.now().isoformat(), su.OUT) if has_error: _error1 = d['error'] _error2 = "<br/>\n".join( map(lambda x: (t(language, str(x))), TT)) _error = "<br/>\n".join([_error1, _error2]) d['error'] = _error return req.getTAL("web/edit/modules/schedule.html", d, macro="schedule_popup")