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)
|