(file) Return to checkprod.py CVS log (file) (dir) Up to [Development] / JSOC / build

  1 arta  1.1 #!/usr/bin/env python
  2           
  3           from __future__ import print_function
  4           import sys
  5           import os
  6           import re
  7           from subprocess import check_output, check_call, CalledProcessError
  8           import smtplib
  9 arta  1.2 sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../base/libs/py'))
 10           from drmsCmdl import CmdlParser
 11 arta  1.1 
 12           # Hard code a bunch of stuff since I don't have time to do this correctly.
 13           PROD_ROOTDIR = '/home/jsoc/cvs/Development'
 14           WAYSTATION = 'waystation'
 15           WAYSTATION_USER = 'arta'
 16           WAYSTATION_DOMAIN = 'sun.stanford.edu'
 17           
 18           RV_SUCCESS = 0
 19 arta  1.3 RV_ERROR_MAIL = 1
 20           RV_ERROR_ARGS = 2
 21 arta  1.1 
 22           # This class changes the current working directory, and restores the original working directory when
 23           # the context is left.
 24           class Chdir:
 25               """Context manager for changing the current working directory"""
 26               def __init__(self, newPath):
 27                   self.newPath = os.path.realpath(newPath)
 28               
 29               def __enter__(self):
 30                   self.savedPath = os.path.realpath(os.getcwd())
 31                   os.chdir(self.newPath)
 32                   cdir = os.path.realpath(os.getcwd())
 33                   if cdir == self.newPath:
 34                       return 0
 35                   else:
 36                       return 1
 37               
 38               def __exit__(self, etype, value, traceback):
 39                   os.chdir(self.savedPath)
 40                   cdir = os.path.realpath(os.getcwd())
 41                   if cdir == self.savedPath:
 42 arta  1.1             return 0
 43                   else:
 44                       return 1
 45           
 46 arta  1.2 def sendMail(localName, domainName, details):
 47 arta  1.1     subject = 'Production Binary Tree Check'
 48               fromAddr = 'jsoc@solarpost.stanford.edu'
 49               toAddrs = [ localName + '@' + domainName ]
 50               msg = 'From: jsoc@solarpost.stanford.edu\nTo: ' + ','.join(toAddrs) + '\nSubject: ' + subject + '\n' + details
 51           
 52               try:
 53                   server = smtplib.SMTP('solarpost.stanford.edu')
 54                   server.sendmail(fromAddr, toAddrs, msg)
 55                   server.quit()
 56               except Exception as exc:
 57                   # If any exception happened, then the email message was not received.
 58                   raise Exception('emailBadrecipient', 'Unable to send email message.', RV_ERROR_MAIL)
 59           
 60 arta  1.2 def getArgs():
 61               optD = {}
 62           
 63               try:
 64                   parser = CmdlParser(usage='%(prog)s [ -h ] [ -m | --mail ]')
 65           
 66                   # Optional
 67                   # Cannot combine metavar with action for some unknown reason.
 68                   parser.add_argument('-m', '--mail', help='Send the waystation user the list of changed files in a mail message', dest='mail', action='store_true')
 69           
 70                   args = parser.parse_args()
 71           
 72                   # Read the series info from
 73               except Exception as exc:
 74                   if len(exc.args) != 2:
 75                       raise # Re-raise
 76           
 77                   etype = exc.args[0]
 78                   msg = exc.args[1]
 79           
 80                   if etype == 'CmdlParser-ArgUnrecognized' or etype == 'CmdlParser-ArgBadformat' or etype == 'CmdlParser':
 81 arta  1.3             raise Exception('getArgs', 'Unable to parse command-line arguments.', RV_ERROR_ARGS)
 82 arta  1.2         else:
 83                       raise # Re-raise.
 84           
 85               optD['mail'] = args.mail
 86           
 87               return optD
 88           
 89 arta  1.1 msg = None
 90           rv = RV_SUCCESS
 91           
 92           
 93           # Run the linux rsync command to see which files have timestamps that are newer than the waystation files.
 94           # CAVEAT: rsync runs differently and takes different arguments on different machines.
 95           #   su - arta
 96           #   cd /home/jsoc/cvs/Development
 97           #   rsync -aluv --dry-run JSOC/ waystation/JSOC
 98           try:
 99 arta  1.2     optD = getArgs()
100 arta  1.1     changedFiles = []
101               with Chdir(PROD_ROOTDIR) as ret:
102                   cmdList = ['rsync', '-aluv', '--dry-run', 'JSOC/', 'waystation/JSOC']
103                   if ret == 0:
104                       resp = check_output(cmdList)
105                       output = resp.decode('utf-8')
106                       
107                       if output:
108                           # Parse out the status field.
109                           outputList = output.splitlines()
110                           firstLine = True
111                           
112                           # One of the bad things about calling an external program is that you cannot control what it does.
113                           # In this case, different implementations of rsync format the output differently. So, take a guess
114                           # and assume the first line is not part of the file list, and that there is a newline separating
115                           # the last item in the file list and the output footer.
116                           regExp = re.compile(r'\s*(\S+)\s*')
117                           
118                           for line in outputList:
119                               if firstLine:
120                                   firstLine = False
121 arta  1.1                         continue
122                               
123                               matchObj = regExp.match(line)
124                               if matchObj is not None:
125                                   # We have a non-empty line.
126                                   # Skip directories. Report files only.
127                                   item = matchObj.group(1)
128                                   if os.path.isfile('JSOC/' + item):
129                                       changedFiles.append(item)
130                                   else:
131                                       continue
132                               else:
133                                   # This line is one past the last item in the file list.
134                                   break
135               
136                           # Now if there is at least one file that changed, send an email to WAYSTATION_USER
137                           if changedFiles and len(changedFiles) >= 1:
138 arta  1.2                     if optD['mail']:
139                                   sendMail(WAYSTATION_USER, WAYSTATION_DOMAIN, 'List of files changed:\n' + '\n'.join(changedFiles))
140                               else:
141                                   print('Files Modified in Production Directory:\n' + '\n'.join(changedFiles))
142           
143 arta  1.1         else:
144                       print('Unable to change directory to ' + PROD_ROOTDIR, file=sys.stderr)
145           
146           except CalledProcessError as exc:
147               if exc.output:
148                   print('Error calling rsync: ' + exc.output, file=sys.stderr)
149           except ValueError:
150               print('Bad arguments to rsync: \n' + '\n'.join(cmdList[1:]))
151           except Exception as exc:
152               if len(exc.args) != 3:
153                   raise # Re-raise
154           
155               etype = exc.args[0]
156           
157               if etype == 'emailBadrecipient':
158                   msg = exc.args[1]
159                   rv = exc.args[2]
160               else:
161                   raise # Re-raise
162           
163           if msg:
164 arta  1.1     print(msg, file=sys.stderr)
165           
166           sys.exit(rv)

Karen Tian
Powered by
ViewCVS 0.9.4