def sendEmailAlert(self, sid, state, time_first_seen_in_new_state):
        '''
        Sends an email to everyone in  the global serverlink_alert_groups about the specified server-link's health problem.
        sid = sid of server which is unhealthy (int)
        state = int
        time = time first seen in this state (secs since epoc)
        '''
        recipients = []
        recipient_groups = xsftp.webui.models.Configuration.objects.all()[0].serverlink_alert_groups.all()
        for group in recipient_groups:
            for user in group.users.all():
                if user not in recipients:
                    recipients.append(user)
        email_addresses = [user.email for user in recipients if user.email]
        server_link = xsftp.webui.models.Server.objects.get(id=sid)
        server_link_name = server_link.server_name
        device_name = xsftp.webui.models.Configuration.objects.all()[0].device_name
        if not email_addresses:
            log(1, "Could not send Server Link Health warning email for Server '%s': No 'Server Link Health Global Alert Groups' have been specified." % server_link_name)
        # instantiate a new Server object, set its state, then extract its html details for that state.
        if server_link.status != state:
            server_link.status = state
        # generate text details, by converting the html healthstrings to text for email rendering.
        myWriter = formatter.DumbWriter()
        myFormatter = formatter.AbstractFormatter(myWriter)
        p = EmailTextParser(myFormatter)
        p.feed(server_link.healthStrings())
        # remove tab characters
        details = p.data.replace('\t','')
        # remove blank lines
        details = "\n".join([line for line in details.split("\n") if line != ''])
        p.close()
        #details = server_link.healthStrings()
        # generate time string
        total_seconds = int(time.time() - time_first_seen_in_new_state)
        days = total_seconds / 86400
        hours = total_seconds % 86400 / 3600
        minutes = total_seconds % 86400 % 3600 / 60
        seconds = total_seconds % 86400 % 3600 % 60
        time_string = "%s days, %s hours, %s minutes, %s seconds" % (days, hours, minutes, seconds)
        message = '''
    This is an automatic message from the Fcombine Device: %(device_name)s

    The Server Link '%(server_link_name)s' has been in unhealthy state %(state)s for %(time_string)s.

    arning - Jobs and Users may not be able to utilise this Server Link until it is repaired. See details below for help on remediating this issue.

    Details are:

    %(details)s
    ''' % {"device_name":device_name, "server_link_name":server_link_name, "state":state, "time_string":time_string, "details":details}
        try:
            email.send_email(subject="Fcombine Server Link Health warning for Server '%s'" % server_link_name, body=message, to=email_addresses)
        except Email_Error, e:
            log(1, "Could not send Server Link Health warning email for Server '%s': %s" % (server_link_name, e))
Example #2
0
	def render_to_email(self):
		recipients = list()
		if self.status:
			# Gather the 'alert on success' users
			# 1) Global Alert Users
			global_groups = xsftp.webui.models.Configuration.objects.all()[0].job_success_alert_groups.all()
			# global_groups is now just a list of groups
			# for each of those groups in global_groups, we want to get out all the users
			for group in global_groups:
				for user in group.users.all():
					if user not in recipients:
						recipients.append(user)
			# 2) Job Specific Groups
			if not job_temp.suppress_group_alerts:
				job_groups = job_temp.alert_groups_on_success.all()
				for group in job_groups:
					for user in group.users.all():
						if user not in recipients:
							recipients.append(user)
			# 3) Job Owner
			if job_temp.alert_owner_on_success and job_temp.owner not in recipients:
				recipients.append(job_temp.owner)
		else:
			# Gather the 'alert on fail' users
			# 1) Global Alert Users
			global_groups = xsftp.webui.models.Configuration.objects.all()[0].job_failure_alert_groups.all()
			# global_groups is now just a list of groups
			# for each of those groups in global_groups, we want to get out all the users
			for group in global_groups:
				for user in group.users.all():
					if user not in recipients:
						recipients.append(user)
			# 2) Job Specific Groups
			if not job_temp.suppress_group_alerts:
				job_groups = job_temp.alert_groups_on_fail.all()
				for group in job_groups:
					for user in group.users.all():
						if user not in recipients:
							recipients.append(user)
			# 3) Job Owner
			if job_temp.alert_owner_on_fail and job_temp.owner not in recipients:
				recipients.append(job_temp.owner)
		email_addresses = [user.email for user in recipients if user.email]
		# Generate some strings that will be used in the message
		# Duration String
		duration = self.end_time - self.start_time
		total_seconds = duration.seconds + (duration.days * 86400)
		hours = total_seconds / 3600
		minutes = total_seconds % 3600 / 60
		seconds = total_seconds % 3600 % 60
		duration_string = "%002d:%002d:%002d" % (hours, minutes, seconds)
		# Data Transferred string
		if self.source_files:
			total_data = reduce(lambda x, y: x + y, [f.file_size for f in self.source_files if f.file_size is not None] or [0])
		else:
			total_data = 0
		total_data = int(total_data)
		if total_data / 1024**3:
			data = "%.2f GB" % (float(total_data)/1024**3)
		elif total_data / 1024**2:
			data = "%.2f MB" % (float(total_data)/1024**2)
		elif total_data / 1024:
			data = "%.2f KB" % (float(total_data)/1024)
		else:
			data = "%s bytes" % total_data
		if not self.source_files:
			data = "0 (no source files selected for copy)"
		# PreScript String
		if job.use_pre_script:
			pre_script_string = "\nPrescript: %s" % job.pre_script.script_name
		else:
			pre_script_string = ""
		if job_temp.use_post_script:
			post_script_string = "\nPostscript: %s" % job_temp.post_script.script_name
		else:
			post_script_string = ""
		# generate the message
		# generate message, starting with pre-script and postscript message blocks
		pre_script_block = post_script_block = ""
		if self.pre_script_output:
			pre_script_block = "\nPre-Script Output\n=================\n***** Return Code:\n%s\n***** Output Data (stdout):\n%s\n***** Output Data (stderr):\n%s\n" % (
				self.pre_script_output[0],
				self.pre_script_output[1],
				(self.pre_script_output[2] or "None"),
			)
		if self.post_script_output:
			post_script_block = "\nPost-Script Output\n==================\n***** Return Code:\n%s\n***** Output Data (stdout):\n%s\n***** Output Data (stderr):\n%s\n" % (
				self.post_script_output[0],
				(self.post_script_output[1] or "None"),
				(self.post_script_output[2] or "None"),
			)
		# generate full message
		message = """
This is an automatic message from Fcombine: %(device_name)s

The Job '%(job_name)s' has %(statusString)s
See attachment for per-file details.

Job Information
===============
Job Name: %(job_name)s
Owner: %(owner)s
Comment: %(comment)s
Run Count: %(count)s%(prescript)s%(postscript)s
%(runnow)s

Transfer Details
================
Source Server Link: %(source)s
Destination Server Link: %(dest)s
Destination Path: %(dest_path)s

Job Results
===========
Status: %(status)s
Message: %(message)s
Start Time: %(start)s
End Time: %(end)s
Duration: %(dur)s
Data Transfer Size: %(data)s
%(pre_script_output)s
%(post_script_output)s
""" % {	"device_name":xsftp.webui.models.Configuration.objects.all()[0].device_name,
		"job_name":job.job_name,
		"owner":job.owner.username,
		"comment":job.comment,
		"count":job.run_count,
		"prescript":pre_script_string,
		"postscript":post_script_string,
		"status":["Success", "Fail"][[True, False].index(self.status)],
		"statusString": ["COMPLETED SUCCESSFULLY.", "FAILED."][[True, False].index(self.status)],
		"message":self.message,
		"start":self.start_time.ctime(),
		"end":self.end_time.ctime(),
		"dur":duration_string,
		"data":data,
		"source":job_temp.source_server.server_name,
		"dest":job_temp.dest_server.server_name,
		"dest_path":job_temp.dest_path,
		"runnow":["", "This job was invoked manually"][self.runnow],
		"pre_script_output":pre_script_block,
		"post_script_output":post_script_block,
		}
		# generate the attachment content
		attachment_content = """Source Files,Destination File Name,Size (bytes),Attempted,Status,Start Time,End Time,Duration (seconds),Message\n"""
		source_strip = len(xsftp.common.constants.SMP_DIR + str(job_temp.source_server.id))
		dest_strip = len(xsftp.common.constants.SMP_DIR + str(job_temp.dest_server.id))
		for f in self.source_files:
			sourceString = "%s:%s" % (job_temp.source_server.server_name, f.src_path[source_strip:])
			if f.dest_path:
				destString = "%s:%s" % (job_temp.dest_server.server_name, f.dest_path[dest_strip:])
			else:
				destString = "None"
			if f.start_time:
				start_string = f.start_time.ctime()
			else:
				start_string = ""
			if f.end_time:
				end_string = f.end_time.ctime()
			else:
				end_string = ""
			if f.end_time:
				duration = (f.end_time - f.start_time).seconds
			else:
				duration = None
			attachment_content += """%(src)s,%(dest)s,%(size)s,%(attempted)s,%(status)s,%(start)s,%(end)s,%(dur)s,%(msg)s\n""" % {"src":sourceString, "dest":destString, "size":f.file_size, "status":["Pass", "Fail"][[True, False].index(f.status)], "attempted":["Yes", "No"][[True, False].index(f.attempted)], "start":start_string, "end":end_string, "dur":duration, "msg":f.message or ""}
		try:
			email.send_email(subject="Fcombine Job Report for job '%s': %s" % (job.job_name, ["SUCCESS", "FAIL"][[True, False].index(self.status)]), body=message, to=email_addresses, attachments=[('Fcombine_Job_Details.csv', attachment_content, 'text/csv')])
		except xsftp.webui.constants.Email_Error, e:
			log("Error sending email report for job '%s': %s" % (job.job_name, e))