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

File: [Development] / JSOC / build / checkprod.py (download) / (as text)
Revision: 1.3, Fri Jan 30 22:59:39 2015 UTC (8 years, 4 months ago) by arta
Branch: MAIN
CVS Tags: Ver_LATEST, Ver_9-5, Ver_9-41, Ver_9-4, Ver_9-3, Ver_9-2, Ver_9-1, Ver_9-0, Ver_8-8, Ver_8-7, Ver_8-12, Ver_8-11, Ver_8-10, NetDRMS_Ver_LATEST, NetDRMS_Ver_9-5, NetDRMS_Ver_9-41, NetDRMS_Ver_9-4, NetDRMS_Ver_9-3, NetDRMS_Ver_9-2, NetDRMS_Ver_9-1, NetDRMS_Ver_9-0, NetDRMS_Ver_8-8, NetDRMS_Ver_8-7, NetDRMS_Ver_8-12, NetDRMS_Ver_8-11, NetDRMS_Ver_8-10, HEAD
Changes since 1.2: +3 -2 lines
Fix exception object construction.

#!/usr/bin/env python

from __future__ import print_function
import sys
import os
import re
from subprocess import check_output, check_call, CalledProcessError
import smtplib
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../base/libs/py'))
from drmsCmdl import CmdlParser

# Hard code a bunch of stuff since I don't have time to do this correctly.
PROD_ROOTDIR = '/home/jsoc/cvs/Development'
WAYSTATION = 'waystation'
WAYSTATION_USER = 'arta'
WAYSTATION_DOMAIN = 'sun.stanford.edu'

RV_SUCCESS = 0
RV_ERROR_MAIL = 1
RV_ERROR_ARGS = 2

# This class changes the current working directory, and restores the original working directory when
# the context is left.
class Chdir:
    """Context manager for changing the current working directory"""
    def __init__(self, newPath):
        self.newPath = os.path.realpath(newPath)
    
    def __enter__(self):
        self.savedPath = os.path.realpath(os.getcwd())
        os.chdir(self.newPath)
        cdir = os.path.realpath(os.getcwd())
        if cdir == self.newPath:
            return 0
        else:
            return 1
    
    def __exit__(self, etype, value, traceback):
        os.chdir(self.savedPath)
        cdir = os.path.realpath(os.getcwd())
        if cdir == self.savedPath:
            return 0
        else:
            return 1

def sendMail(localName, domainName, details):
    subject = 'Production Binary Tree Check'
    fromAddr = 'jsoc@solarpost.stanford.edu'
    toAddrs = [ localName + '@' + domainName ]
    msg = 'From: jsoc@solarpost.stanford.edu\nTo: ' + ','.join(toAddrs) + '\nSubject: ' + subject + '\n' + details

    try:
        server = smtplib.SMTP('solarpost.stanford.edu')
        server.sendmail(fromAddr, toAddrs, msg)
        server.quit()
    except Exception as exc:
        # If any exception happened, then the email message was not received.
        raise Exception('emailBadrecipient', 'Unable to send email message.', RV_ERROR_MAIL)

def getArgs():
    optD = {}

    try:
        parser = CmdlParser(usage='%(prog)s [ -h ] [ -m | --mail ]')

        # Optional
        # Cannot combine metavar with action for some unknown reason.
        parser.add_argument('-m', '--mail', help='Send the waystation user the list of changed files in a mail message', dest='mail', action='store_true')

        args = parser.parse_args()

        # Read the series info from
    except Exception as exc:
        if len(exc.args) != 2:
            raise # Re-raise

        etype = exc.args[0]
        msg = exc.args[1]

        if etype == 'CmdlParser-ArgUnrecognized' or etype == 'CmdlParser-ArgBadformat' or etype == 'CmdlParser':
            raise Exception('getArgs', 'Unable to parse command-line arguments.', RV_ERROR_ARGS)
        else:
            raise # Re-raise.

    optD['mail'] = args.mail

    return optD

msg = None
rv = RV_SUCCESS


# Run the linux rsync command to see which files have timestamps that are newer than the waystation files.
# CAVEAT: rsync runs differently and takes different arguments on different machines.
#   su - arta
#   cd /home/jsoc/cvs/Development
#   rsync -aluv --dry-run JSOC/ waystation/JSOC
try:
    optD = getArgs()
    changedFiles = []
    with Chdir(PROD_ROOTDIR) as ret:
        cmdList = ['rsync', '-aluv', '--dry-run', 'JSOC/', 'waystation/JSOC']
        if ret == 0:
            resp = check_output(cmdList)
            output = resp.decode('utf-8')
            
            if output:
                # Parse out the status field.
                outputList = output.splitlines()
                firstLine = True
                
                # One of the bad things about calling an external program is that you cannot control what it does.
                # In this case, different implementations of rsync format the output differently. So, take a guess
                # and assume the first line is not part of the file list, and that there is a newline separating
                # the last item in the file list and the output footer.
                regExp = re.compile(r'\s*(\S+)\s*')
                
                for line in outputList:
                    if firstLine:
                        firstLine = False
                        continue
                    
                    matchObj = regExp.match(line)
                    if matchObj is not None:
                        # We have a non-empty line.
                        # Skip directories. Report files only.
                        item = matchObj.group(1)
                        if os.path.isfile('JSOC/' + item):
                            changedFiles.append(item)
                        else:
                            continue
                    else:
                        # This line is one past the last item in the file list.
                        break
    
                # Now if there is at least one file that changed, send an email to WAYSTATION_USER
                if changedFiles and len(changedFiles) >= 1:
                    if optD['mail']:
                        sendMail(WAYSTATION_USER, WAYSTATION_DOMAIN, 'List of files changed:\n' + '\n'.join(changedFiles))
                    else:
                        print('Files Modified in Production Directory:\n' + '\n'.join(changedFiles))

        else:
            print('Unable to change directory to ' + PROD_ROOTDIR, file=sys.stderr)

except CalledProcessError as exc:
    if exc.output:
        print('Error calling rsync: ' + exc.output, file=sys.stderr)
except ValueError:
    print('Bad arguments to rsync: \n' + '\n'.join(cmdList[1:]))
except Exception as exc:
    if len(exc.args) != 3:
        raise # Re-raise

    etype = exc.args[0]

    if etype == 'emailBadrecipient':
        msg = exc.args[1]
        rv = exc.args[2]
    else:
        raise # Re-raise

if msg:
    print(msg, file=sys.stderr)

sys.exit(rv)

Karen Tian
Powered by
ViewCVS 0.9.4