tk5-c90-projects/mvs_job.py

115 lines
3.4 KiB
Python
Raw Normal View History

2025-10-19 12:48:47 +00:00
#!/usr/bin/env python3
import sys
import subprocess
import tempfile
import os
2026-02-03 14:39:29 +00:00
# Force temp files into a folder inside your project (fully owned by you)
custom_temp_dir = os.path.join(os.getcwd(), "tmp")
os.makedirs(custom_temp_dir, exist_ok=True)
tempfile.tempdir = custom_temp_dir
2025-10-19 12:48:47 +00:00
2025-10-19 13:33:13 +00:00
SRCLIB = "src"
JCLLIB = "jcl"
2025-10-19 12:48:47 +00:00
MVSHOST = "oldcomputernerd.com"
RDRPORT = 3505
2026-02-03 11:15:18 +00:00
MVS_PASSWORD = os.environ.get("MVS_BATCH_PASSWORD")
2025-10-19 12:48:47 +00:00
2026-02-03 16:10:03 +00:00
def create_jcl_payload(local_file, dataset_name, member_name):
2025-10-19 13:33:13 +00:00
with open(local_file, 'r') as f:
2026-02-03 16:10:03 +00:00
sysin = f.readlines()
2025-10-19 12:48:47 +00:00
# PDS member: Use IEBUPDTE
jcl = f"""
//UPLOAD JOB (ACCT),'UPLOAD',
2026-02-03 11:15:18 +00:00
// USER=@05054,PASSWORD={MVS_PASSWORD},
2025-10-19 12:48:47 +00:00
// CLASS=A,MSGCLASS=H,NOTIFY=@05054
//COPY EXEC PGM=IEBUPDTE,PARM=NEW
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD DUMMY
//SYSUT2 DD DSN={dataset_name},DISP=MOD,UNIT=SYSDA,
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//SYSIN DD *
"""
# Append control statement, source lines, end, and terminator (no leading space on ./)
jcl += f"./ ADD NAME={member_name}\n"
2026-02-03 16:10:03 +00:00
for line in sysin:
2025-10-19 12:48:47 +00:00
line = line.rstrip('\n')[:80]
jcl += line.ljust(80) + "\n"
jcl += "./ ENDUP\n"
jcl += "/*\n"
2026-02-03 14:39:29 +00:00
2026-02-03 16:10:03 +00:00
return jcl
def upload_source(local_file, dataset_name, member_name, mvshost=MVSHOST):
"""Upload source code to MVS PDS member"""
# Read the source file
# full path will come from the job runner
# filepath = os.path.join(SRCLIB, local_file)
payload = create_jcl_payload(local_file, dataset_name, member_name)
2025-10-19 12:48:47 +00:00
# Write JCL to temporary file and submit via netcat
2026-02-03 16:10:03 +00:00
2025-10-19 12:48:47 +00:00
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.jcl') as tmpfile:
2026-02-03 16:10:03 +00:00
tmpfile.write(payload)
tmpfile.flush()
2025-10-19 12:48:47 +00:00
tmpfile_path = tmpfile.name
try:
2026-02-03 16:10:03 +00:00
with open(tmpfile_path, 'rb') as f:
subprocess.run(
['nc', '-w', '5', mvshost, str(RDRPORT)],
input=f.read(),
check=True,
capture_output=True
)
2025-10-19 12:48:47 +00:00
print(f"Uploaded {local_file} to {dataset_name}({member_name})")
return 0
except subprocess.CalledProcessError as e:
print(f"Upload failed: {e}")
2026-02-03 16:10:03 +00:00
print("stderr:", e.stderr.decode(errors='ignore'))
2025-10-19 12:48:47 +00:00
return 1
2026-02-03 16:10:03 +00:00
2025-10-19 12:48:47 +00:00
finally:
2026-02-03 16:10:03 +00:00
# Clean up outside
2026-02-04 14:42:23 +00:00
os.unlink(tmpfile_path)
2025-10-19 12:48:47 +00:00
def submit_jcl(job, mvshost="oldcomputernerd.com"):
"""Submit JCL job from local directory"""
subjcl = os.path.join(JCLLIB, f"{job}.jcl")
if not os.path.exists(subjcl):
print(f"JCL file {subjcl} not found")
return 1
subcmd = f"nc -w 5 {mvshost} {RDRPORT} < {subjcl}"
2025-10-19 12:48:47 +00:00
try:
subprocess.run(subcmd, shell=True, check=True)
print(f"Submitted JCL job: {job}")
return 0
except subprocess.CalledProcessError as e:
print(f"JCL submission failed: {e}")
return 1
if __name__ == "__main__":
if len(sys.argv) < 5:
print("Usage: mvs_job.py <local_source_file> <dataset> <member> <job_name> [mvshost]")
sys.exit(1)
local_file = sys.argv[1]
dataset_name = sys.argv[2]
member_name = sys.argv[3]
job = sys.argv[4]
mvshost = sys.argv[5] if len(sys.argv) > 5 else MVSHOST
# Step 1: Upload source to PDS
if upload_source(local_file, dataset_name, member_name, mvshost) != 0:
sys.exit(1)
# Step 2: Submit JCL job
submit_jcl(job, mvshost)