#!/opt/python/bin/python # Triton Resource path for python interpreter # this script checks the availability of disk space on /projects for stsi and stsi1 # and reports via email (stsi1 and 2 share a storage pool so reporting on either # one of them covers both filesystems) # includes certain users based on the date and time, and on the amount of remaining # storage (currently set to 2 Terabytes or 2**41) # todo: add this command: /opt/lustre/bin/lfs df /phase1 # and send email for status of phase1 # also can add du output for specific users and locations on request for limited times import os import smtplib import locale import subprocess from datetime import date, time, datetime def GetHumanReadable(size, precision=2): suffixes=['B','KB','MB','GB','TB'] suffixIndex = 0 while size > 1024: suffixIndex += 1 # increment the index of the suffix if size >= 1048576: size = size/1000.0 # apply the division else: size = size/1024.0 # convert to 1-K block size return "%.*f %s" % (precision, size, suffixes[suffixIndex]) # return "%d %s" % (size, suffixes[suffixIndex]) #THRESHOLD = 10**12 * 2 # exactly 2 Trillion (2 Tebibytes) THRESHOLD = 2**41 # 2 Terabytes (2199023255552L) # Recipients for customized notifications RCP1 = "mdwyer@sdsc.edu" #Mike Dwyer (SDSC) RCP2 = "mmiller@sdsc.edu" #Mark Miller (SDSC) RCP3 = "slevy@scripps.edu" #Sam Levy RCP4 = "carson.andrew@scrippshealth.org" #Andrew Carson (STSI) RCP5 = "nicholas.thomas@scrippshealth.org" #Tom Nicholas (STSI) RCP6 = "carlandt@scripps.edu" #Tristan Carland (STSI) RCP7 = "tnorden@scripps.edu" #Trina Norden-K (STSI) RCP8 = "rtewhey@scripps.edu" #Ryan Tewhey (STSI) RCP9 = "gfzhang@scripps.edu" #Guangfa Zhang (STSI) RCP10 = "vbansal@scripps.edu" #V. Bansal (STSI) RCP11 = "rhawkins@sdsc.edu" #Ron Hawkins (SDSC) stsi_fsystem = "/projects/stsi" stsi1_fsystem = "/projects/stsi1" stsi2_fsystem = "/projects/stsi2" stsi3_fsystem = "/projects/stsi3" stsi4_fsystem = "/projects/stsi4" ## using os module here, deprecated per python.org docs #stsi_proj = os.statvfs(stsi_fsystem) #stsi1_proj = os.statvfs(stsi1_fsystem) #stsi_available = stsi_proj.f_bavail * stsi_proj.f_frsize #stsi1_available = stsi1_proj.f_bavail * stsi1_proj.f_frsize ## this uses the approved module for the same calculations ## use the third line of this output, and the third column (of five) ## which is the number of available 1-K (1024-byte) blocks df_stsi = subprocess.check_output(["df", stsi_fsystem]) df_out = [] # temp variable df_out2 = ""; # temp variable stsi_sub_avail = [] # subprocess-derived df_out = df_stsi.split("\n") df_out2 = df_out[2] stsi_sub_avail = df_out2.split() stsi_sub_avail_num = int(stsi_sub_avail[2]) * 1024 # using 1-K blocks, not 1000-byte blocks df_stsi1 = subprocess.check_output(["df", stsi1_fsystem]) df_out = [] df_out2 = ""; stsi1_sub_avail = [] # subprocess-derived df_out = df_stsi1.split("\n") df_out2 = df_out[2] stsi1_sub_avail = df_out2.split() stsi1_sub_avail_num = int(stsi1_sub_avail[2]) * 1000 df_stsi2 = subprocess.check_output(["df", stsi2_fsystem]) df_out = [] df_out2 = ""; stsi2_sub_avail = [] # subprocess-derived df_out = df_stsi2.split("\n") df_out2 = df_out[2] stsi2_sub_avail = df_out2.split() stsi2_sub_avail_num = int(stsi2_sub_avail[2]) * 1000 df_stsi3 = subprocess.check_output(["df", stsi3_fsystem]) df_out = [] df_out2 = ""; stsi3_sub_avail = [] # subprocess-derived df_out = df_stsi3.split("\n") df_out2 = df_out[2] stsi3_sub_avail = df_out2.split() stsi3_sub_avail_num = int(stsi3_sub_avail[2]) * 1000 df_stsi4 = subprocess.check_output(["df", stsi4_fsystem]) df_out = [] df_out2 = ""; stsi4_sub_avail = [] # subprocess-derived df_out = df_stsi4.split("\n") df_out2 = df_out[2] stsi4_sub_avail = df_out2.split() stsi4_sub_avail_num = int(stsi4_sub_avail[2]) * 1000 gb_stsi = subprocess.check_output(["/opt/gold/bin/gbalance", "-p", "stsi-group"]) # format email message sender = 'triton-support@sdsc.edu' msg_subject = 'Triton Cluster STSI Available Storage Summary' locale.setlocale(locale.LC_ALL, "en_US") stsi_space_avail = locale.format("%d", int(stsi_sub_avail_num), grouping=True) stsi_space_avail_hr = GetHumanReadable(stsi_sub_avail_num) stsi1_space_avail = locale.format("%d", stsi1_sub_avail_num, grouping=True) stsi1_space_avail_hr = GetHumanReadable(stsi1_sub_avail_num) stsi2_space_avail = locale.format("%d", stsi2_sub_avail_num, grouping=True) stsi2_space_avail_hr = GetHumanReadable(stsi2_sub_avail_num) stsi3_space_avail = locale.format("%d", stsi3_sub_avail_num, grouping=True) stsi3_space_avail_hr = GetHumanReadable(stsi3_sub_avail_num) stsi4_space_avail = locale.format("%d", stsi4_sub_avail_num, grouping=True) stsi4_space_avail_hr = GetHumanReadable(stsi4_sub_avail_num) today = date.today() dt = datetime.now() hour = dt.hour # set up the receivers list #receivers = ['slevy@scripps.edu', 'mmiller@sdsc.edu', 'carson.andrew@scrippshealth.org', 'nicholas.thomas@scrippshealth.org'] # By default, send to Mike, Mark, Andrew, Tom receivers = ['mjd2160@gmail.com', RCP1, RCP2, RCP4, RCP5] test_receivers = [RCP1] if (stsi_sub_avail_num <= THRESHOLD or stsi1_sub_avail_num <= THRESHOLD or stsi3_sub_avail_num <= THRESHOLD or stsi4_sub_avail_num <= THRESHOLD): receivers.append(RCP6) # send to Tristan receivers.append(RCP7) # send to Trina receivers.append(RCP8) # send to Ryan receivers.append(RCP9) # send to Guangfa receivers.append(RCP10) # send to Vikas elif (today.weekday() == 1 and dt.hour == 7): receivers.append(RCP6) # send to Tristan receivers.append(RCP11) # send to Ron #print "%s: %s" % ("receivers list", receivers) # format the message content # added separate calculations for stsi1 and stsi2; if the values are same, we assume they share the same pool # and report only one value; if they are different, we assume different pools and report each one #msg_body = "Disk space available on %s:\t%s\t(%s bytes)" %(stsi_fsystem, stsi_space_avail_hr, stsi_space_avail) #msg_body = msg_body + "\nDisk space available on %s:\t%s\t(%s bytes)" %(stsi1_fsystem, stsi1_space_avail_hr, stsi1_space_avail) msg_body = "Disk space available on partition /projects/stsi:\n" msg_body = msg_body + "\t%s (%s bytes)" %(stsi_space_avail_hr, stsi_space_avail) if (stsi1_sub_avail_num != stsi2_sub_avail_num): msg_body = msg_body + "\n\nDisk space available on partition /projects/stsi1:\n" msg_body = msg_body + "\t%s (%s bytes)" %(stsi1_space_avail_hr, stsi1_space_avail) msg_body = msg_body + "\n\nDisk space available on partition /projects/stsi2:\n" msg_body = msg_body + "\t%s (%s bytes)" %(stsi2_space_avail_hr, stsi2_space_avail) else: msg_body = msg_body + "\n\nDisk space available on partitions /projects/stsi1 and /projects/stsi2 combined:\n" msg_body = msg_body + "\t%s (%s bytes)" %(stsi1_space_avail_hr, stsi1_space_avail) msg_body = msg_body + "\n\nDisk space available on partition /projects/stsi3:\n" msg_body = msg_body + "\t%s (%s bytes)" %(stsi3_space_avail_hr, stsi3_space_avail) msg_body = msg_body + "\n\nDisk space available on partition /projects/stsi4:\n" msg_body = msg_body + "\t%s (%s bytes)" %(stsi4_space_avail_hr, stsi4_space_avail) msg_body = msg_body + "\n\nAccount Balance:\n%s" %(gb_stsi) # format the complete message, including header message = """From: Triton Support To: Mike Dwyer Subject: %s %s """ %(msg_subject, msg_body) # attempt to send the message try: smtpObj = smtplib.SMTP('localhost') # smtpObj.sendmail(sender, test_receivers, message) smtpObj.sendmail(sender, receivers, message) print "Successfully sent email" except SMTPException: print "Error: unable to send email" ## these os calls are deprecated in favor of the subprocess module calls below #du_msg = os.system("du -sh /phase1/mdwyer") #df_msg = os.system("df /phase1") #du_info = du_msg.split("\n") #print "%s%s" % ("Phase1 du:", du_info) #print "%s%s" % ("Phase1 df:", df_msg) ## use these in favor of the os module for future compatability #df_stsi = subprocess.check_output(["df", "/projects/stsi"]) #print "%s%s" % ("df /projects/stsi output:\n", df_stsi) #df_stsi12 = subprocess.check_output(["df", "/projects/stsi1"]) #print "%s%s" % ("df /projects/stsi12 output:\n", df_stsi12) #df_phase1 = subprocess.check_output(["df", "/phase1"]) #print "%s%s" % ("df /phase1 output:\n", df_phase1) #du_stsi2 = subprocess.check_output(["du", "-sh", "/projects/stsi2/mdwyer"]) #print "%s%s" % ("du /projects/stsi2/mdwyer output:\n", du_stsi2) #du_phase1 = subprocess.check_output(["du", "-sh", "/phase1/mdwyer"]) #print "%s%s" % ("du phase1/mdwyer output:\n", du_phase1)