def _copy_ds(ds, bk_ds): """Copy the contents of a data set to another Arguments: ds {str} -- The source data set to be copied from. Should be SEQ or VSAM bk_dsn {str} -- The destination data set to copy to. Raises: BackupError: When copying data fails """ module = AnsibleModuleHelper(argument_spec={}) _allocate_model(bk_ds, ds) repro_cmd = """ REPRO - INDATASET({0}) - OUTDATASET({1})""".format(ds, bk_ds) rc, out, err = module.run_command( "mvscmdauth --pgm=idcams --sysprint=* --sysin=stdin", data=repro_cmd) if rc != 0 and rc != 12: datasets.delete(bk_ds) raise BackupError( "Unable to backup data set {0}; stdout: {1}; stderr: {2}".format( ds, out, err)) if rc != 0 and is_empty(ds): rc = 0 return rc
def run_sample(): dsn_sample_jcl = datasets.hlq() + ".SAMPLE.JCL" dsn_with_mem_sample_jcl = dsn_sample_jcl + "(UPTIME)" # NOTE - data set does NOT need to exist prior to running this sample. # create and write JCL to data set datasets.write(dataset=dsn_with_mem_sample_jcl, content=jcl_sample) # submit job job_sample = jobs.submit(dsn_with_mem_sample_jcl) print("Details - sample job") print("id:", job_sample.id) print("name:", job_sample.name) print("owner:", job_sample.owner) print("status:", job_sample.status) print("rc:", job_sample.rc) print("Waiting for job completion, then refresh and print status, rc...") job_sample.wait() job_sample.refresh() print("status: ", job_sample.status) print("rc: ", job_sample.rc) dd_stdout = jobs.read_output(job_sample.id, 'UPTIME', 'STDOUT') # print the stdout produced by job print("The contents of the STDOUT DD:") print(dd_stdout) # cleanup: # cancels and removes job from jes system job_sample.purge() # delete data set datasets.delete(dsn_sample_jcl)
def mvs_file_backup(dsn, bk_dsn=None): """Create a backup data set for an MVS data set Arguments: dsn {str} -- The name of the data set to backup. It could be an MVS PS/PDS/PDSE/VSAM(KSDS), etc. bk_dsn {str} -- The name of the backup data set. Raises: BackupError: When backup data set exists. BackupError: When creation of backup data set fails. """ dsn = _validate_data_set_name(dsn).upper() if is_member(dsn): if not bk_dsn: bk_dsn = extract_dsname(dsn) + "({0})".format(temp_member_name()) bk_dsn = _validate_data_set_name(bk_dsn).upper() response = datasets._copy(dsn, bk_dsn) if response.rc != 0: raise BackupError("Unable to backup {0} to {1}".format( dsn, bk_dsn), rc=response.rc, stdout=response.stdout_response, stderr=response.stderr_response) else: if not bk_dsn: bk_dsn = datasets.tmp_name(datasets.hlq()) bk_dsn = _validate_data_set_name(bk_dsn).upper() cp_rc = _copy_ds(dsn, bk_dsn) if cp_rc == 12: # The data set is probably a PDS or PDSE # Delete allocated backup that was created when attempting to use _copy_ds() # Safe to delete because _copy_ds() would have raised an exception if it did # not successfully create the backup data set, so no risk of it predating module invocation datasets.delete(bk_dsn) _allocate_model(bk_dsn, dsn) rc, out, err = _copy_pds(dsn, bk_dsn) if rc != 0: raise BackupError( "Unable to backup data set {0} to {1}".format(dsn, bk_dsn)) return bk_dsn
def _copy_vsam_to_temp_data_set(self, ds_name): """ Copy VSAM data set to a temporary sequential data set """ mvs_rc = 0 vsam_size = self._get_vsam_size(ds_name) sysprint = sysin = out_ds_name = None try: sysin = data_set.DataSet.create_temp("MVSTMP") sysprint = data_set.DataSet.create_temp("MVSTMP") out_ds_name = data_set.DataSet.create_temp("MSVTMP", space_primary=vsam_size, space_type="K") repro_sysin = " REPRO INFILE(INPUT) OUTFILE(OUTPUT) " datasets.write(sysin, repro_sysin) dd_statements = [] dd_statements.append( types.DDStatement(name="sysin", definition=types.DatasetDefinition(sysin))) dd_statements.append( types.DDStatement(name="input", definition=types.DatasetDefinition(ds_name))) dd_statements.append( types.DDStatement( name="output", definition=types.DatasetDefinition(out_ds_name))) dd_statements.append( types.DDStatement( name="sysprint", definition=types.DatasetDefinition(sysprint))) mvs_rc = mvscmd.execute_authorized(pgm="idcams", dds=dd_statements) except OSError as err: self._fail_json(msg=str(err)) except Exception as err: if datasets.exists(out_ds_name): datasets.delete(out_ds_name) if mvs_rc != 0: self._fail_json( msg=( "Non-zero return code received while executing MVSCmd " "to copy VSAM data set {0}".format(ds_name)), rc=mvs_rc, ) self._fail_json( msg= ("Failed to call IDCAMS to copy VSAM data set {0} to a temporary" " sequential data set".format(ds_name)), stderr=str(err), rc=mvs_rc, ) finally: datasets.delete(sysprint) datasets.delete(sysin) return out_ds_name
def _fetch_vsam(self, src, is_binary, encoding=None): """Copy the contents of a VSAM to a sequential data set. Afterwards, copy that data set to a USS file. """ temp_ds = self._copy_vsam_to_temp_data_set(src) file_path = self._fetch_mvs_data(temp_ds, is_binary, encoding) rc = datasets.delete(temp_ds) if rc != 0: os.remove(file_path) self._fail_json( msg="Unable to delete temporary data set {0}".format(temp_ds), rc=rc) return file_path
def mvs_convert_encoding( self, src, dest, from_code, to_code, src_type=None, dest_type=None ): """Convert the encoding of the data from 1) USS to MVS(PS, PDS/E VSAM) 2) MVS to USS 3) MVS to MVS Arguments: src: {str} -- The input MVS data set or USS path to be converted dest: {str} -- The output MVS data set or USS path to be converted from_code: {str} -- The source code set of the input MVS data set to_code: {str} -- The destination code set of the output MVS data set Keyword Arguments: src_type {[type]} -- The input MVS data set or type: PS, PDS, PDSE, VSAM(KSDS) (default: {None}) dest_type {[type]} -- The output MVS data set type (default: {None}) Returns: boolean -- Indicate whether the conversion is successful or not """ src = self._validate_data_set_or_path(src) dest = self._validate_data_set_or_path(dest) from_code = self._validate_encoding(from_code) to_code = self._validate_encoding(to_code) convert_rc = False temp_ps = None temp_src = src temp_dest = dest try: if src_type == "PS": temp_src_fo = NamedTemporaryFile() temp_src = temp_src_fo.name rc, out, err = copy.copy_ps2uss(src, temp_src) if src_type == "PO": temp_src = mkdtemp() rc, out, err = copy.copy_pds2uss(src, temp_src) if src_type == "VSAM": reclen, space_u = self.listdsi_data_set(src.upper()) temp_ps = self.temp_data_set(reclen, space_u) rc, out, err = copy.copy_vsam_ps(src.upper(), temp_ps) temp_src_fo = NamedTemporaryFile() temp_src = temp_src_fo.name rc, out, err = copy.copy_ps2uss(temp_ps, temp_src) if dest_type == "PS" or dest_type == "VSAM": temp_dest_fo = NamedTemporaryFile() temp_dest = temp_dest_fo.name if dest_type == "PO": temp_dest = mkdtemp() rc = self.uss_convert_encoding_prev(temp_src, temp_dest, from_code, to_code) if rc: if not dest_type: convert_rc = True else: if dest_type == "VSAM": reclen, space_u = self.listdsi_data_set(dest.upper()) temp_ps = self.temp_data_set(reclen, space_u) rc, out, err = copy.copy_uss2mvs(temp_dest, temp_ps, "PS") rc, out, err = copy.copy_vsam_ps(temp_ps, dest.upper()) convert_rc = True elif dest_type == "PO": for (dir, subdir, files) in walk(temp_dest): for file in files: temp_file = path.join(dir, file) rc, out, err = copy.copy_uss2mvs(temp_file, dest, "PO") convert_rc = True else: rc, out, err = copy.copy_uss2mvs(temp_dest, dest, dest_type) convert_rc = True except Exception: raise finally: if temp_ps: datasets.delete(temp_ps) if temp_src and temp_src != src: if os.path.isdir(temp_src): shutil.rmtree(temp_src) if temp_dest and temp_dest != dest: if os.path.isdir(temp_dest): shutil.rmtree(temp_dest) return convert_rc
def smpe_list(target_zone="GLOBAL", list_options=None, high_level_qualifier="SYS1"): """ This function does the heavy lifting. It performs the function that is contained in the JCL. It sets up the DD statements and issues the call to the executable. """ # Initialize DD List dd_list = [] # and the temporary dataset temp_dataset = None # setup the filename just in case sysin_file_name = None # get the defaults from the yaml file defaults = get_defaults("./SMPElistDefaults.yaml") try: # Setup base DDs dd_list.append( DDStatement("SMPCSI", DatasetDefinition(defaults["SMPECSI"]["dataset"])) ) dd_list.append(DDStatement("SMPLOG", "DUMMY")) dd_list.append(DDStatement("SMPLOGA", "DUMMY")) # Create Temporary File temp_dataset_name = datasets.tmp_name(high_level_qualifier) datasets.create( temp_dataset_name, type="PDS", primary_space=(defaults["TEMP_DATASET"]["primary_space"]).strip(), secondary_space=(defaults["TEMP_DATASET"]["secondary_space"]).strip(), block_size=3200, record_format="FB", record_length=80, volumes=(defaults["TEMP_DATASET"]["volume"]).strip(), directory_blocks=10, ) # add it to the ddList dd_list.append(DDStatement("SMPWRK6", DatasetDefinition(temp_dataset_name))) # define the input for the program make - sure the input is EBCIDIC sysin_file_name = defaults["SMPECNTL"]["filename"] with open(sysin_file_name, mode="w", encoding="cp1047") as file: file.write(f"SET BDY({target_zone}).\n") if list_options is None: file.write("LIST.\n") else: file.write(f"LIST {list_options}.\n") dd_list.append(DDStatement("SMPCNTL", FileDefinition(sysin_file_name))) # define the place for the output to go output_dataset_name = datasets.tmp_name(high_level_qualifier) datasets.create( output_dataset_name, type="SEQ", primary_space=(defaults["OUTPUT_DATASET"]["primary_space"]).strip(), secondary_space=(defaults["OUTPUT_DATASET"]["secondary_space"]).strip(), volumes=(defaults["OUTPUT_DATASET"]["volume"]).strip(), ) dd_list.append(DDStatement("SMPLIST", DatasetDefinition(output_dataset_name))) # execute the program command_return_code = mvscmd.execute_authorized(pgm="GIMSMP", dds=dd_list) except Exception as e: sys.stderr.write("Error processing command environment...\n") sys.stderr.write(f"Exception information: {e}\n") sys.exit(1) finally: # remove temporary dataset and file if temp_dataset: datasets.delete(temp_dataset_name) if sysin_file_name is not None: os.remove(sysin_file_name) print(f"Output can be found in: {output_dataset_name}\n") return command_return_code