Skip to content

Commit

Permalink
add end message support for stopZos
Browse files Browse the repository at this point in the history
  • Loading branch information
Greg Keuken committed Aug 22, 2023
1 parent 859c204 commit f49e4e7
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 16 deletions.
31 changes: 23 additions & 8 deletions stopZos
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
#
# stopzos accepts three parameters
# -c command name - z/OS console command to initiate system shutdown (default is '%netv shutsys' which works on ZD&T ADCD)
# -z taskname - task to monitor to determine if z/OS is completely down (default is JES2)
# -z taskname - task to monitor to determine if z/OS is completely down, this option is mutually exclusive with -m
# -m message - message to wait for to signify z/OS is completely down, this option is mutually exclusive with -z
# -t timeout - time to wait for shutdown to complete (default is 300 seconds, 5 minutes)
# -awsstop - if specified then after timeout or z/OS is down then command awsstop is executed
# -noverify - if specified then issue no prompts to confirm/abort
Expand All @@ -27,7 +28,6 @@ getLoggedUser()
# Lets get the status of zPDT Emulator and z/OS
checkZpdt()


#get Devmap Information
if zdtPyApi.zdtConf != '':
findDmInfo(zdtPyApi.loggedUser, zdtPyApi.zdtConf)
Expand All @@ -43,12 +43,21 @@ if zdtPyApi.zdtStat != 'up':
prRed("zPDT Emulator is not active, z/OS is already down")

else:
chkEndTask()
if zdtPyApi.endTask:
chkEndTask()
if zdtPyApi.endMessage:
file_stats = os.stat(zdtPyApi.curLogFile)
logLen = file_stats.st_size
print('Existing Log length: '+str(logLen))
chkEndMsg(logLen)
totTime = 0
intTime = 30 # interval, in seconds, of when to recheck if endTask is down
if zdtPyApi.zosIsUp == 'yes':
getIplInfo()
prCyan("stopZos using task "+zdtPyApi.endTask+" to determine z/OS status")
if zdtPyApi.endTask:
prCyan("stopZos using task "+zdtPyApi.endTask+" to determine z/OS status")
if zdtPyApi.endMessage:
prCyan("stopZos using Message "+zdtPyApi.endMessage+" to determine z/OS status")
prCyan("stopZos will shutdown z/OS using command: "+zdtPyApi.shutCmd)
prCyan("stopZos will timeout after: "+str(zdtPyApi.stopTime)+" seconds")
if zdtPyApi.awsstop == 'Y':
Expand All @@ -74,10 +83,16 @@ else:
prRed('Timeout is approaching, attempting cancel of remaining JES2 dependent tasks')
stopJesTasks()
stopFlag = 'Y'
chkEndTask()
if zdtPyApi.endTask:
chkEndTask()
if zdtPyApi.endMessage:
chkEndMsg(zdtPyApi.logSeek)
if zdtPyApi.zosIsUp == 'no':
totTime = zdtPyApi.stopTime
prCyan("z/OS now considered down, task "+zdtPyApi.endTask+" has ended")
if zdtPyApi.endTask:
prCyan("z/OS now considered down, task "+zdtPyApi.endTask+" has ended")
if zdtPyApi.endMessage:
prCyan("z/OS now considered down, message "+zdtPyApi.endMessage+" has been observed in the Log")
if zdtPyApi.awsstop == 'Y':
prRed("Issuing zPDT awsstop")
subprocess.call(["awsstop"])
Expand All @@ -86,7 +101,7 @@ else:
prRed("Re-IPL starting using IPL string: ipl "+zdtPyApi.IPL_Dev+" parm "+zdtPyApi.IODF_Dev+zdtPyApi.LD_Parm)
subprocess.run(["ipl", zdtPyApi.IPL_Dev, "parm", zdtPyApi.IODF_Dev+zdtPyApi.LD_Parm])
if zdtPyApi.zosIsUp == 'yes':
prRed("stopZos has timed out waiting for z/OS to end. Specified end Task "+zdtPyApi.endTask+" did not end in specified timeout perios")
prRed("stopZos has timed out waiting for z/OS to end. Specified end Task did not end or end Message did not appear in log in specified timeout period")
if zdtPyApi.reipl == 'Y':
prRed("Re-IPL starting using IPL string: ipl "+zdtPyApi.IPL_Dev+" parm "+zdtPyApi.IODF_Dev+zdtPyApi.LD_Parm)
subprocess.run(["ipl", zdtPyApi.IPL_Dev, "parm", zdtPyApi.IODF_Dev+zdtPyApi.LD_Parm])
Expand All @@ -96,7 +111,7 @@ else:
subprocess.call(["awsstop"])

else:
prRed("z/OS already appears to be down, "+zdtPyApi.endTask+" was not found")
prRed("z/OS already appears to be down, specified end task "+zdtPyApi.endTask+" was not found or end message has been observed in console log: "+zdtPyApi.endMessage)
if zdtPyApi.reipl == 'Y':
prRed("Re-IPL not possible, current IPL string unknown")
if zdtPyApi.awsstop == 'Y':
Expand Down
43 changes: 35 additions & 8 deletions zdtPyApi.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,25 @@ def stopJesTasks():
cantask = str('CANCEL '+tasknm)
sendOprMsg(cantask, curLogFile, 1, 't')

# Used for stopZos to check if a task is still running or not
# Used for stopZos to check if z/OS is still up, based on Message
def chkEndMsg(intLogSeek):
global zosIsUp, logSeek
foundMsg = 'no'
zosIsUp = 'yes'
logSeek = intLogSeek
with open(curLogFile, "rb") as iplLog:
iplLog.seek(logSeek)
readBytes = iplLog.read(1024)
while readBytes != b'' and foundMsg == 'no':
logSeek+=len(readBytes)-500 #back up a litle just in case
print("checking for "+str(endMessage)+" in file: "+str(curLogFile)+" from byte: " +str(logSeek-1524)+" to byte: "+str(logSeek))
if endMessage in str(readBytes):
foundMsg = 'yes'
zosIsUp = 'no'
readBytes = iplLog.read(1024)


# Used for stopZos to check if a task is still running or not, based on Task name
def chkEndTask():
global zosIsUp
chkStat = str('d a,'+endTask)
Expand Down Expand Up @@ -106,9 +124,12 @@ def printHelp():
elif 'stopZos' in sys.argv[0]:
prCyan("** stopZos Input Requirements: **")
print("Run this utility with linux user that starts zPDT and IPLs z/OS")
print("At least one of -g or -z should be specified, but NOT BOTH.")
print(" ")
print(" ")
print("-c z/OS Shutdown Command Optional: The z/OS Console command to shutdown z/OS. Default is %netv shutsys, which only works for ADCD")
print("-z Final z/OS Subsystem Optional: Task to check to ensure z/OS is completely down. Default is JES2")
print("-z Final z/OS Subsystem Optional: Task to check to ensure z/OS is completely down. Mutually exclusive with -g")
print("-g Final z/OS Message Optional: Message to check for to signify that z/OS is completely down. Mutually exclusive with -z")
print("-t Timeout (seconds) Optional. Default is 300 Seconds.")
print("-awsstop Optional. If specified then zPDT command awsstop will be executed after timeout or after z/OS is down.")

Expand Down Expand Up @@ -322,16 +343,17 @@ def readArgs():
arglist = ['-d','-v','-p','-q','-r','-x','--help']
elif 'stopZos' in sys.argv[0]:
pfunc = 'stopZos'
arglist = ['-c','-z','-t','-awsstop','-reipl','-noverify','--help']
arglist = ['-c','-z','-g','-t','-awsstop','-reipl','-noverify','--help']
else:
pfunc = 'zdtmsg'
arglist = ['-w','--help']
arg_len = len(sys.argv)
if arg_len < 2 and 'stopZos' not in sys.argv[0]:
# if arg_len < 2 and 'stopZos' not in sys.argv[0]:
if arg_len < 2:
printHelp()
sys.exit()
size_list = ['1','3','9','27','54']
global stopTime, shutCmd, endTask, progPath, subJcl, newSize, volSer, smsFlag, inVol, autoMnt, inUid, volDir, upDmap, slpTime, sshSub, zosIp, awsstop, noverify, pdsName, memName, searchStr, replStr, reipl
global stopTime, shutCmd, endTask, endMessage, progPath, subJcl, newSize, volSer, smsFlag, inVol, autoMnt, inUid, volDir, upDmap, slpTime, sshSub, zosIp, awsstop, noverify, pdsName, memName, searchStr, replStr, reipl
progPath = os.path.realpath(__file__).strip('zdtPyApi.py')
progPath = os.path.realpath(__file__).strip('zdtPyApi.pyc')
try:
Expand All @@ -355,7 +377,8 @@ def readArgs():
reipl = 'N'
awsstop = 'no'
noverify = 'N'
endTask = 'JES2'
endMessage = ''
endTask = ''
upDmap = 'y'
newSize = '1'
inUid = 'IBMUSER'
Expand All @@ -368,7 +391,7 @@ def readArgs():
while x < arg_len:
x += 1
if sys.argv[x] not in arglist:
if 'stopZos' in sys.argv[0] and x == 0:
if 'stopZos' in sys.argv[0] and x == 1:
pass
elif 'zdtmsg' in sys.argv[0] and x == 1:
pass
Expand All @@ -385,6 +408,9 @@ def readArgs():
elif sys.argv[x] == '-z':
endTask = sys.argv[x+1].upper()
x += 1
elif sys.argv[x] == '-g':
endMessage = sys.argv[x+1].upper()
x += 1
elif sys.argv[x] == '-t':
stopTime = int(sys.argv[x+1])
x += 1
Expand Down Expand Up @@ -459,7 +485,8 @@ def readArgs():

if 'stopZos' in sys.argv[0] and reipl == 'Y' and awsstop == 'Y':
raise ValueError('-awsstop and -reipl are mutually exclusive')

if 'stopZos' in sys.argv[0] and endMessage and endTask:
raise ValueError('-g and -z options are mutually exclusive')
#if not os.path.exists(volDir) and pfunc != 'zdtmsg':
if not os.path.exists(volDir+inVol) and pfunc != 'zdtmsg' and pfunc != 'zdtVcreate':
raise ValueError('Volume not found in current working directory or directory specified, switch to correct directory or use appropriate -d option')
Expand Down

0 comments on commit f49e4e7

Please sign in to comment.