def default_username_validator(configuration, username, force_email=True): """The default username validator restricted to only accept usernames that are valid in grid daemons, namely a possible user, sharelink, job or jupyter mount ID. The optional and default enabled force_email option is used to further limit user_id values to actual email addresses, as always required in grid daemons. """ logger = configuration.logger # logger.debug("username: %s, force_email: %s" % (username, force_email)) if possible_gdp_user_id(configuration, username): return True elif possible_user_id(configuration, username): if not force_email: return True elif is_valid_email_address(username, configuration.logger): return True if possible_sharelink_id(configuration, username): return True if possible_job_id(configuration, username): return True if possible_jupyter_mount_id(configuration, username): return True return False
def validate_notify(configuration, job, errors): """Validates job specified vs. syntactic correctness""" if skip_validation(configuration, job, 'NOTIFY'): return True # Lightweight version of shared/notification.notify_user() only validating # syntax of notify addreses job_value = job['NOTIFY'] syntax_is_valid = True for notify_line in job_value: if not syntax_is_valid: errors['NOTIFY'] = std_err_desc(job_value) break supported_im_protocols = configuration.notify_protocols email_keyword_list = ['mail', 'email'] notify_line_colon_split = notify_line.split(':', 1) notify_line_first_part = notify_line_colon_split[0].strip() if notify_line_first_part in supported_im_protocols: # There is no validation of IM-addresses. See comment in # shared/notification.notify_user() continue elif notify_line_first_part in email_keyword_list: recipients = notify_line.replace('%s: ' % \ notify_line_first_part, '').strip() if recipients.strip().upper() in ['SETTINGS', '']: continue else: for recipient in recipients: if not syntax_is_valid: errors['NOTIFY'] = std_err_desc(job_value) break else: syntax_is_valid = \ is_valid_email_address(recipient, configuration.logger) else: syntax_is_valid = False return not errors.has_key('NOTIFY')
def notify_user( jobdict, args_list, status, logger, statusfile, configuration, ): """Send notification messages about job to user. User settings are used if notification fields are left empty or set to 'SETTINGS'. Please note that this function may take a long time to deliver notifications, or even block forever if an IM is requested and no IM daemon is running. Thus it should be run in a separate thread or process if blocking is not allowed. Please take a look at notify_user_thread() if that is a requirement. """ # Usage records: quickly hacked in here. # later, we might want a general plugin / hook interface # first of all, write out the usage record (if configured) ur_destination = configuration.usage_record_dir if ur_destination: logger.debug('XML Usage Record directory %s' % ur_destination) usage_record = UsageRecord(configuration, logger) usage_record.fill_from_dict(jobdict) # we use the job_id as a file name (should be unique) usage_record.write_xml(ur_destination + os.sep + jobdict['JOB_ID'] + '.xml') jobid = jobdict['JOB_ID'] for notify_line in jobdict['NOTIFY']: logger.debug('notify line: %s' % notify_line) (header, message) = create_notify_message(jobdict, args_list, status, statusfile, configuration) supported_protocols = ['jabber', 'msn', 'icq', 'aol', 'yahoo'] notify_line_colon_split = notify_line.split(':', 1) if notify_line_colon_split[0].strip() in supported_protocols: protocol = notify_line_colon_split[0] recipients = notify_line_colon_split[1].strip() all_dest = [] # Empty or if recipients.strip().upper() in ['SETTINGS', '']: # read from personal settings settings_dict = load_settings(jobdict['USER_CERT'], configuration) if not settings_dict\ or not settings_dict.has_key(protocol.upper()): logger.info('Settings dict does not have %s key' % protocol.upper()) continue all_dest = settings_dict[protocol.upper()] else: all_dest.append(recipients) for single_dest in all_dest: logger.debug('notifying %s about %s' % (single_dest, jobid)) # NOTE: Check removed because icq addresses are numbers and not "emails" # if not is_valid_email_address(single_dest, logger): # not a valid address (IM account names are on standard email format) # continue............................ if send_instant_message( single_dest, protocol, header, message, logger, configuration, ): logger.info('Instant message sent to %s protocol: %s telling that %s %s' % (single_dest, protocol, jobid, status)) else: logger.error('Instant message NOT sent to %s protocol %s jobid: %s' % (single_dest, protocol, jobid)) else: notify_line_first_part = notify_line_colon_split[0].strip() all_dest = [] if notify_line_first_part in email_keyword_list: logger.info("'%s' notify_line_first_part found in email_keyword_list" % notify_line_first_part) recipients = notify_line.replace('%s: ' % notify_line_first_part, '').strip() if recipients.strip().upper() in ['SETTINGS', '']: # read from personal settings settings_dict = load_settings(jobdict['USER_CERT'], configuration) if not settings_dict: logger.info('Could not load settings_dict') continue if not settings_dict.has_key('EMAIL'): logger.info('Settings dict does not have EMAIL key' ) continue all_dest = settings_dict['EMAIL'] else: all_dest.append(recipients) elif is_valid_email_address(notify_line, logger): all_dest.append(notify_line) # send mails for single_dest in all_dest: logger.info('email destination %s' % single_dest) # verify specified address is valid if not is_valid_email_address(single_dest, logger): logger.info('%s is NOT a valid email address!' % single_dest) # not a valid email address continue if send_email(single_dest, header, message, logger, configuration): logger.info('email sent to %s telling that %s %s' % (single_dest, jobid, status)) else: logger.error('email NOT sent to %s, jobid: %s' % (single_dest, jobid))