Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v1.10.0] [zos_copy] zos_copy migration to ZOAU v1.3.0 #1222

Merged
merged 9 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelogs/fragments/1222-zoau-migration-zos_copy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
trivial:
- zos_copy - Migrated the module to use ZOAU v1.3.0.
(https://github.com/ansible-collections/ibm_zos_core/pull/1222).
12 changes: 10 additions & 2 deletions plugins/module_utils/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,13 +273,21 @@ def _get_job_status(job_id="*", owner="*", job_name="*", dd_name=None, dd_scan=T
job["owner"] = entry.owner

job["ret_code"] = dict()
job["ret_code"]["msg"] = "{0} {1}".format(entry.status, entry.return_code)

# From v1.3.0, ZOAU sets unavailable job fields as None, instead of '?'.
# This new way of constructing msg allows for a better empty message.
# "" instead of "None None".
job["ret_code"]["msg"] = "{0} {1}".format(
entry.status if entry.status else "",
entry.return_code if entry.return_code else ""
).strip()

job["ret_code"]["msg_code"] = entry.return_code
job["ret_code"]["code"] = None
if entry.return_code and len(entry.return_code) > 0:
if entry.return_code.isdigit():
job["ret_code"]["code"] = int(entry.return_code)
job["ret_code"]["msg_text"] = entry.status
job["ret_code"]["msg_text"] = entry.status if entry.status else "?"

# Beginning in ZOAU v1.3.0, the Job class changes svc_class to
# service_class.
Expand Down
44 changes: 23 additions & 21 deletions plugins/modules/zos_copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,7 @@


from ansible_collections.ibm.ibm_zos_core.plugins.module_utils.import_handler import (
MissingZOAUImport,
ZOAUImportError,
)
from ansible_collections.ibm.ibm_zos_core.plugins.module_utils.mvs_cmd import (
idcams
Expand All @@ -829,6 +829,7 @@
import math
import tempfile
import os
import traceback

if PY3:
from re import fullmatch
Expand All @@ -839,7 +840,8 @@
try:
from zoautil_py import datasets, opercmd
except Exception:
datasets = MissingZOAUImport()
datasets = ZOAUImportError(traceback.format_exc())
opercmd = ZOAUImportError(traceback.format_exc())


class CopyHandler(object):
Expand Down Expand Up @@ -918,7 +920,7 @@ def copy_to_seq(
if self.force_lock:
copy_args["options"] += " -f"

response = datasets._copy(new_src, dest, None, **copy_args)
response = datasets._copy(new_src, dest, **copy_args)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey could you review if is possible to remove underscore zoau functions ? Not saying is wrong or bad but do remember Demetri said to remove if possible.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed all calls to hidden ZOAU functions and ran the pipeline again for zos_copy.

Screenshot 2024-02-16 at 16 19 14
Screenshot 2024-02-16 at 16 19 55

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And for zos_job_submit

Screenshot 2024-02-16 at 16 33 38
Screenshot 2024-02-16 at 16 33 53

if response.rc != 0:
raise CopyOperationError(
msg="Unable to copy source {0} to {1}".format(new_src, dest),
Expand Down Expand Up @@ -988,7 +990,7 @@ def _copy_tree(self, entries, src, dest, dirs_exist_ok=False):
else:
opts = dict()
opts["options"] = ""
response = datasets._copy(src_name, dest_name, None, **opts)
response = datasets._copy(src_name, dest_name, **opts)
if response.rc > 0:
raise Exception(response.stderr_response)
shutil.copystat(src_name, dest_name, follow_symlinks=True)
Expand Down Expand Up @@ -1356,7 +1358,7 @@ def _copy_to_file(self, src, dest, conv_path, temp_path):
else:
opts = dict()
opts["options"] = ""
response = datasets._copy(new_src, dest, None, **opts)
response = datasets._copy(new_src, dest, **opts)
if response.rc > 0:
raise Exception(response.stderr_response)
shutil.copystat(new_src, dest, follow_symlinks=True)
Expand Down Expand Up @@ -1563,7 +1565,7 @@ def _mvs_copy_to_uss(
)
else:
if self.executable:
response = datasets._copy(src, dest, None, alias=True, executable=True)
response = datasets._copy(src, dest, alias=True, executable=True)

if response.rc != 0:
raise CopyOperationError(
Expand Down Expand Up @@ -1852,7 +1854,7 @@ def dump_data_set_member_to_file(data_set_member, is_binary):
if is_binary:
copy_args["options"] = "-B"

response = datasets._copy(data_set_member, temp_path, None, **copy_args)
response = datasets._copy(data_set_member, temp_path, **copy_args)
if response.rc != 0 or response.stderr_response:
raise DataSetMemberAttributeError(data_set_member)

Expand Down Expand Up @@ -2315,7 +2317,7 @@ def get_attributes_of_any_dataset_created(
volume=volume
)
else:
src_attributes = datasets.listing(src_name)[0]
src_attributes = datasets.list_datasets(src_name)[0]
size = int(src_attributes.total_space)
params = get_data_set_attributes(
dest,
Expand Down Expand Up @@ -2397,8 +2399,8 @@ def allocate_destination_data_set(
try:
# Dumping the member into a file in USS to compute the record length and
# size for the new data set.
src_attributes = datasets.listing(src_name)[0]
record_length = int(src_attributes.lrecl)
src_attributes = datasets.list_datasets(src_name)[0]
record_length = int(src_attributes.record_length)
temp_dump = dump_data_set_member_to_file(src, is_binary)
create_seq_dataset_from_file(
temp_dump,
Expand All @@ -2417,11 +2419,11 @@ def allocate_destination_data_set(
if src_ds_type in data_set.DataSet.MVS_PARTITIONED:
data_set.DataSet.allocate_model_data_set(ds_name=dest, model=src_name, executable=executable, asa_text=asa_text, vol=volume)
elif src_ds_type in data_set.DataSet.MVS_SEQ:
src_attributes = datasets.listing(src_name)[0]
src_attributes = datasets.list_datasets(src_name)[0]
# The size returned by listing is in bytes.
size = int(src_attributes.total_space)
record_format = src_attributes.recfm
record_length = int(src_attributes.lrecl)
record_format = src_attributes.record_format
record_length = int(src_attributes.record_length)
dest_params = get_data_set_attributes(
dest,
size,
Expand Down Expand Up @@ -2507,8 +2509,8 @@ def allocate_destination_data_set(
asa_text,
volume
)
dest_attributes = datasets.listing(dest)[0]
record_format = dest_attributes.recfm
dest_attributes = datasets.list_datasets(dest)[0]
record_format = dest_attributes.record_format
dest_params["type"] = dest_ds_type
dest_params["record_format"] = record_format
return True, dest_params
Expand Down Expand Up @@ -2730,8 +2732,8 @@ def run_module(module, arg_def):
src_ds_type = data_set.DataSet.data_set_type(src_name)

if src_ds_type not in data_set.DataSet.MVS_VSAM:
src_attributes = datasets.listing(src_name)[0]
if src_attributes.recfm == 'FBA' or src_attributes.recfm == 'VBA':
src_attributes = datasets.list_datasets(src_name)[0]
if src_attributes.record_format == 'FBA' or src_attributes.record_format == 'VBA':
src_has_asa_chars = True
else:
raise NonExistentSourceError(src)
Expand Down Expand Up @@ -2785,17 +2787,17 @@ def run_module(module, arg_def):
elif not dest_exists and asa_text:
dest_has_asa_chars = True
elif dest_exists and dest_ds_type not in data_set.DataSet.MVS_VSAM:
dest_attributes = datasets.listing(dest_name)[0]
if dest_attributes.recfm == 'FBA' or dest_attributes.recfm == 'VBA':
dest_attributes = datasets.list_datasets(dest_name)[0]
if dest_attributes.record_format == 'FBA' or dest_attributes.record_format == 'VBA':
dest_has_asa_chars = True

if dest_data_set and (dest_data_set.get('record_format', '') == 'FBA' or dest_data_set.get('record_format', '') == 'VBA'):
dest_has_asa_chars = True
elif not dest_exists and asa_text:
dest_has_asa_chars = True
elif dest_exists and dest_ds_type not in data_set.DataSet.MVS_VSAM:
dest_attributes = datasets.listing(dest_name)[0]
if dest_attributes.recfm == 'FBA' or dest_attributes.recfm == 'VBA':
dest_attributes = datasets.list_datasets(dest_name)[0]
if dest_attributes.record_format == 'FBA' or dest_attributes.record_format == 'VBA':
dest_has_asa_chars = True

if dest_ds_type in data_set.DataSet.MVS_PARTITIONED:
Expand Down
8 changes: 6 additions & 2 deletions tests/functional/modules/test_zos_copy_func.py
Original file line number Diff line number Diff line change
Expand Up @@ -4347,16 +4347,21 @@ def test_backup_pds(ansible_zos_module, args):
def test_copy_data_set_to_volume(ansible_zos_module, volumes_on_systems, src_type):
hosts = ansible_zos_module
source = get_tmp_ds_name()
source_member = f"{source}(MEM)"
dest = get_tmp_ds_name()
volumes = Volume_Handler(volumes_on_systems)
volume_1 = volumes.get_available_vol()

if volume_1 == "SCR03":
volume = volumes.get_available_vol()
volumes.free_vol(volume_1)
volume_1 = volume

try:
hosts.all.zos_data_set(name=source, type=src_type, state='present')
hosts.all.zos_data_set(name=source_member, type="member", state='present')
if src_type != "seq":
hosts.all.zos_data_set(name=source_member, type="member", state='present')

copy_res = hosts.all.zos_copy(
src=source,
dest=dest,
Expand Down Expand Up @@ -4406,7 +4411,6 @@ def test_copy_ksds_to_non_existing_ksds(ansible_zos_module):
finally:
hosts.all.zos_data_set(name=dest_ds, state="absent")


@pytest.mark.vsam
@pytest.mark.parametrize("force", [False, True])
def test_copy_ksds_to_existing_ksds(ansible_zos_module, force):
Expand Down
Loading