Skip to content

Commit ecfb60f

Browse files
authored
[Enhancement] [zos_stat] Add support to stat migrated data sets (#2075)
* [Enhancement] [zos_stat] Add support for aliases (#2048) * Update fragment * Add support for migrated data sets * Move recall to an earlier step * Fix trailing comma * Fix handling of migrated data sets when not recalled * Fix tsocmd validation * Update RST file * Add changelog fragment * Fix escaping * Fix pep8 issue * Update module docs
1 parent 187c7f9 commit ecfb60f

File tree

4 files changed

+142
-3
lines changed

4 files changed

+142
-3
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
minor_changes:
2+
- zos_stat - Added support to recall migrated data sets and return
3+
its attributes.
4+
(https://github.com/ansible-collections/ibm_zos_core/pull/2075)

docs/source/modules/zos_stat.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ name
3232

3333
Data sets can be sequential, partitioned (PDS), partitioned extended (PDSE), VSAMs or generation data sets (GDS).
3434

35+
This option doesn't accept the use of wilcards (? and *).
36+
3537
| **required**: True
3638
| **type**: str
3739
@@ -71,6 +73,24 @@ sms_managed
7173
| **default**: False
7274
7375

76+
recall
77+
Whether to recall a migrated data set to fully query its attributes.
78+
79+
If set to ``false``, the module will return a limited amount of information for a migrated data set.
80+
81+
Recalling a data set will make the module take longer to execute.
82+
83+
Ignored when the data set is not found to be migrated.
84+
85+
The data set will not be migrated again afterwards.
86+
87+
The data set will not get recalled when running the module in check mode.
88+
89+
| **required**: False
90+
| **type**: bool
91+
| **default**: False
92+
93+
7494
tmp_hlq
7595
Override the default high level qualifier (HLQ) for temporary data sets.
7696

plugins/module_utils/data_set.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,6 +2102,59 @@ def _build_volume_string_iehprogm(volumes):
21022102
volume_string += single_volume_string + ")\n"
21032103
return volume_string
21042104

2105+
@staticmethod
2106+
def check_if_data_set_migrated(name):
2107+
"""Compares the output of datasets.list_dataset_names with and
2108+
without migrated data set names to check if name has been migrated.
2109+
2110+
Parameters
2111+
----------
2112+
name : str
2113+
Name of a data set.
2114+
2115+
Returns
2116+
-------
2117+
bool
2118+
Whether the data set has been migrated.
2119+
"""
2120+
has_been_migrated = False
2121+
2122+
non_migrated_list = datasets.list_dataset_names(name, migrated=False)
2123+
migrated_list = datasets.list_dataset_names(name, migrated=True)
2124+
2125+
if name in migrated_list and name not in non_migrated_list:
2126+
has_been_migrated = True
2127+
2128+
return has_been_migrated
2129+
2130+
@staticmethod
2131+
def recall_migrated_data_set(name, module, tmp_hlq=None):
2132+
"""Recalls a data set using HRECALL.
2133+
2134+
Parameters
2135+
----------
2136+
name : str
2137+
Name of a data set.
2138+
module : AnsibleModuleHelper
2139+
Ansible object capable of executing commands.
2140+
2141+
Keyword Parameters
2142+
------------------
2143+
tmp_hlq : str
2144+
Temp HLQ to use with mvscmdauth.
2145+
2146+
Returns
2147+
-------
2148+
tuple(int, str, str)
2149+
Return code, standard output and standard error from
2150+
the HRECALL call.
2151+
"""
2152+
name = name.replace('$', '\\$')
2153+
recall_cmd = f"""tsocmd "HRECALL '{name}'" """
2154+
rc, stdout, stderr = module.run_command(recall_cmd)
2155+
2156+
return rc, stdout, stderr
2157+
21052158
@staticmethod
21062159
def get_name_if_data_set_is_alias(name, tmp_hlq=None):
21072160
"""Checks the catalog to see if 'name' corresponds to a data set

plugins/modules/zos_stat.py

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
or a UNIX System Services file path, to query.
3636
- Data sets can be sequential, partitioned (PDS), partitioned
3737
extended (PDSE), VSAMs or generation data sets (GDS).
38+
- This option doesn't accept the use of wilcards (? and *).
3839
type: str
3940
required: true
4041
aliases:
@@ -77,6 +78,20 @@
7778
type: bool
7879
required: false
7980
default: false
81+
recall:
82+
description:
83+
- Whether to recall a migrated data set to fully query its
84+
attributes.
85+
- If set to C(false), the module will return a limited amount of
86+
information for a migrated data set.
87+
- Recalling a data set will make the module take longer to execute.
88+
- Ignored when the data set is not found to be migrated.
89+
- The data set will not be migrated again afterwards.
90+
- The data set will not get recalled when running the module in
91+
check mode.
92+
type: bool
93+
required: false
94+
default: false
8095
tmp_hlq:
8196
description:
8297
- Override the default high level qualifier (HLQ) for temporary data
@@ -1708,7 +1723,8 @@ def __init__(
17081723
ds_type,
17091724
tmp_hlq=None,
17101725
missing_volumes=None,
1711-
alias=None
1726+
alias=None,
1727+
migrated=False
17121728
):
17131729
"""Create a new handler that will handle the query of a sequential or
17141730
partitioned data set. This subclass should only be instantiated by
@@ -1725,6 +1741,7 @@ def __init__(
17251741
missing_volumes (list, optional) -- List of volumes where a data set was searched
17261742
but not found.
17271743
alias (str, optional) -- Alias of the data set that the user provided.
1744+
migrated (bool, optional) -- Whether it is a migrated data set.
17281745
"""
17291746
super().__init__(
17301747
name,
@@ -1737,6 +1754,7 @@ def __init__(
17371754
alias=alias
17381755
)
17391756
self.missing_volumes = missing_volumes
1757+
self.migrated = migrated
17401758

17411759
def query(self):
17421760
"""Uses LISTDSI to query facts about a data set, while also handling
@@ -1754,6 +1772,14 @@ def query(self):
17541772
data = super().query()
17551773
attributes = {}
17561774

1775+
if self.migrated:
1776+
data['attributes'] = fill_missing_attrs(
1777+
self._parse_attributes(attributes),
1778+
self.expected_attrs
1779+
)
1780+
1781+
return data
1782+
17571783
try:
17581784
# First creating a temp data set to hold the LISTDSI script.
17591785
# All options are meant to allocate just enough space for it.
@@ -2293,7 +2319,8 @@ def get_data_set_handler(
22932319
volumes,
22942320
module,
22952321
tmp_hlq=None,
2296-
sms_managed=False
2322+
sms_managed=False,
2323+
recall=False
22972324
):
22982325
"""Returns the correct handler needed depending on the type of data set
22992326
we will query.
@@ -2305,6 +2332,7 @@ def get_data_set_handler(
23052332
module (AnsibleModule) -- Ansible object with the task's context.
23062333
tmp_hlq (str, optional) -- Temp HLQ for certain data set operations.
23072334
sms_managed (bool, optional) -- Whether the data set is managed by SMS.
2335+
recall (bool, optional) -- Whether a migrated data set should be recalled.
23082336
23092337
Returns
23102338
-------
@@ -2321,6 +2349,27 @@ def get_data_set_handler(
23212349

23222350
alias_name = None
23232351

2352+
has_been_migrated = DataSet.check_if_data_set_migrated(name)
2353+
if has_been_migrated:
2354+
if recall and not module.check_mode:
2355+
rc, stdout, stderr = DataSet.recall_migrated_data_set(
2356+
name,
2357+
module,
2358+
tmp_hlq=tmp_hlq
2359+
)
2360+
2361+
# Ignoring whatever comes out of stderr because tsocmd decides
2362+
# to pollute it even when the command runs fine.
2363+
if rc != 0:
2364+
raise QueryException(
2365+
'An error ocurred while recalling a migrated data set.',
2366+
rc,
2367+
stdout,
2368+
stderr
2369+
)
2370+
else:
2371+
return NonVSAMDataSetHandler(name, 'MIGRAT', module, sms_managed, None, migrated=True)
2372+
23242373
try:
23252374
is_an_alias, base_name = DataSet.get_name_if_data_set_is_alias(
23262375
name,
@@ -2385,6 +2434,7 @@ def get_facts_handler(
23852434
volumes=None,
23862435
tmp_hlq=None,
23872436
sms_managed=False,
2437+
recall=False,
23882438
file_args=None
23892439
):
23902440
"""Returns the correct handler needed depending on the type of resource
@@ -2398,14 +2448,15 @@ def get_facts_handler(
23982448
volumes (list, optional) -- Volumes where a data set is allocated.
23992449
tmp_hlq (str, optional) -- Temp HLQ for certain data set operations.
24002450
sms_managed (bool, optional) -- Whether a data set is managed by SMS.
2451+
recall (bool, optional) -- Whether migrated data sets should be recalled.
24012452
file_args (dict, optional) -- Options affecting how a file is query.
24022453
24032454
Returns
24042455
-------
24052456
FactsHandler -- Handler for data sets/GDGs/aggregates/files.
24062457
"""
24072458
if resource_type == 'data_set':
2408-
return get_data_set_handler(name, volumes, module, tmp_hlq, sms_managed)
2459+
return get_data_set_handler(name, volumes, module, tmp_hlq, sms_managed, recall)
24092460
elif resource_type == 'gdg':
24102461
return GenerationDataGroupHandler(name, module, tmp_hlq)
24112462
elif resource_type == 'file':
@@ -2441,6 +2492,11 @@ def run_module():
24412492
'required': False,
24422493
'default': False
24432494
},
2495+
'recall': {
2496+
'type': 'bool',
2497+
'required': False,
2498+
'default': False
2499+
},
24442500
'tmp_hlq': {
24452501
'type': 'str',
24462502
'required': False
@@ -2490,6 +2546,10 @@ def run_module():
24902546
'arg_type': 'bool',
24912547
'required': False
24922548
},
2549+
'recall': {
2550+
'arg_type': 'bool',
2551+
'required': False
2552+
},
24932553
'tmp_hlq': {
24942554
'arg_type': 'str',
24952555
'required': False
@@ -2527,6 +2587,7 @@ def run_module():
25272587
resource_type = module.params.get('type')
25282588
tmp_hlq = module.params.get('tmp_hlq')
25292589
sms_managed = module.params.get('sms_managed')
2590+
recall = module.params.get('recall')
25302591
file_args = {
25312592
'follow': module.params.get('follow'),
25322593
'get_mime': module.params.get('get_mime'),
@@ -2542,6 +2603,7 @@ def run_module():
25422603
volumes,
25432604
tmp_hlq,
25442605
sms_managed,
2606+
recall,
25452607
file_args
25462608
)
25472609
except QueryException as err:

0 commit comments

Comments
 (0)