Skip to content

Commit f9de6d5

Browse files
authored
Merge branch 'dev' into bug/1940/mount_handle_fsumf168
2 parents 2d44965 + 26941e3 commit f9de6d5

File tree

8 files changed

+339
-159
lines changed

8 files changed

+339
-159
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
trivial:
2+
- test_zos_volume_init.py - Adds support dynamic volumes and allocations for testing.
3+
(https://github.com/ansible-collections/ibm_zos_core/pull/2030).
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
bugfixes:
2+
- zos_data_set - Attempting to create a data set with the same name on a
3+
different volume did not work, nor did it report a failure.
4+
The fix now informs the user that if the data set is cataloged on a
5+
different volume, it needs to be uncataloged before using the data
6+
set module to create a new data set on a different volume.
7+
(https://github.com/ansible-collections/ibm_zos_core/pull/2057).
8+
trivial:
9+
- data_set - added validation logic to compare requested volumes against
10+
cataloged volumes.
11+
Improved error messaging when volume conflicts occur during data set creation on
12+
different volume.
13+
(https://github.com/ansible-collections/ibm_zos_core/pull/2057).
14+
- zos_data_set - Added documentation about potential false positive scenarios.
15+
(https://github.com/ansible-collections/ibm_zos_core/pull/2057).

plugins/module_utils/data_set.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,19 @@ def ensure_present(
203203
changed = False
204204
if DataSet.data_set_cataloged(name, tmphlq=tmp_hlq):
205205
present = True
206+
# Validate volume conflicts when:
207+
# 1. Dataset exists in catalog (present=True).
208+
# 2. User hasn't requested replacement (replace=False).
209+
# 3. Specific volumes were requested (volumes parameter provided).
210+
if present and not replace and volumes:
211+
cataloged_volumes = DataSet.data_set_cataloged_volume_list(name, tmphlq=tmp_hlq)
212+
requested_volumes = [vol.upper() for vol in volumes]
213+
if not any(vol.upper() in requested_volumes for vol in cataloged_volumes):
214+
raise DatasetCatalogedOnDifferentVolumeError(
215+
name=name,
216+
existing_volumes=cataloged_volumes,
217+
requested_volumes=volumes
218+
)
206219

207220
if not present:
208221
try:
@@ -3121,6 +3134,17 @@ def __init__(self, data_set, volumes, rc, message=""):
31213134
super().__init__(self.msg)
31223135

31233136

3137+
class DatasetCatalogedOnDifferentVolumeError(Exception):
3138+
def __init__(self, name, existing_volumes, requested_volumes):
3139+
existing_vol_str = ", ".join(existing_volumes) if existing_volumes else "none"
3140+
requested_vol_str = ", ".join(requested_volumes) if requested_volumes else "none"
3141+
self.msg = (
3142+
"Data set {0} is cataloged with volume {1}, if you want to create data set {0} "
3143+
"in volume {2} uncatalog the data set first and then create it."
3144+
).format(name, existing_vol_str, requested_vol_str)
3145+
super().__init__(self.msg)
3146+
3147+
31243148
class DatasetUncatalogError(Exception):
31253149
def __init__(self, data_set, rc):
31263150
"""Error during uncaloging of a data set.

plugins/modules/zos_data_set.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@
104104
- >
105105
If I(state=uncataloged) and the data set is found, the data set is uncataloged,
106106
module completes successfully with I(changed=True).
107+
- >
108+
If I(state=present), the data set is already cataloged and I(volumes) is provided,
109+
the module will compare the volumes where it is cataloged against the provided I(volumes).
110+
If they don't match, the module will fail with an error indicating the data set is cataloged
111+
on a different volume.
112+
To resolve this, you must first uncatalog the data set before creating it on the new volume.
113+
- >
114+
If I(state=present), the data set is already cataloged, I(volumes) is provided,
115+
and the volumes match exactly, no action is taken and the module completes successfully
116+
with I(changed=False).
107117
required: false
108118
type: str
109119
default: present
@@ -1905,18 +1915,18 @@ def run_module():
19051915
for data_set_params in data_set_param_list:
19061916
# this returns MVSDataSet, Member or GenerationDataGroup
19071917
data_set = get_data_set_handler(**data_set_params)
1908-
result["changed"] = perform_data_set_operations(
1918+
current_changed = perform_data_set_operations(
19091919
data_set=data_set,
19101920
state=data_set_params.get("state"),
19111921
replace=data_set_params.get("replace"),
19121922
tmp_hlq=data_set_params.get("tmp_hlq"),
19131923
force=data_set_params.get("force"),
1914-
) or result.get("changed", False)
1924+
)
1925+
result["changed"] = result["changed"] or current_changed
19151926
except Exception as e:
19161927
module.fail_json(msg=repr(e), **result)
1917-
else:
1918-
if module.params.get("replace"):
1919-
result["changed"] = True
1928+
if module.params.get("replace"):
1929+
result["changed"] = True
19201930
module.exit_json(**result)
19211931

19221932

tests/conftest.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
__metaclass__ = type
1515
import pytest
1616
from ibm_zos_core.tests.helpers.ztest import ZTestHelper
17-
from ibm_zos_core.tests.helpers.volumes import get_volumes, get_volumes_with_vvds
17+
from ibm_zos_core.tests.helpers.volumes import get_volumes, get_volumes_with_vvds, get_volume_and_unit
1818
from ansible.plugins.action import ActionBase
1919
import sys
2020
from mock import MagicMock
@@ -158,6 +158,20 @@ def volumes_with_vvds(ansible_zos_module, request):
158158
yield volumes_with_vvds
159159

160160

161+
@pytest.fixture(scope="session")
162+
def volumes_unit_on_systems(ansible_zos_module, request):
163+
""" Call the pytest-ansible plugin to check volumes on the system and work properly a list by session."""
164+
path = request.config.getoption("--zinventory")
165+
list_volumes = None
166+
167+
if path is None:
168+
src = request.config.getoption("--zinventory-raw")
169+
helper = ZTestHelper.from_args(src)
170+
list_volumes = helper.get_volume_and_unit()
171+
else:
172+
list_volumes = get_volume_and_unit(ansible_zos_module, path)
173+
174+
yield list_volumes
161175

162176
# * We no longer edit sys.modules directly to add zoautil_py mock
163177
# * because automatic teardown is not performed, leading to mock pollution

tests/functional/modules/test_zos_data_set_func.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,6 @@ def test_multi_volume_creation_uncatalog_and_catalog_nonvsam(ansible_zos_module,
751751
finally:
752752
hosts.all.zos_data_set(name=default_data_set_name, state="absent")
753753

754-
755754
def test_multi_volume_creation_uncatalog_and_catalog_vsam(ansible_zos_module, volumes_on_systems):
756755
volumes = Volume_Handler(volumes_on_systems)
757756
volume_1 = volumes.get_available_vol()
@@ -789,6 +788,36 @@ def test_multi_volume_creation_uncatalog_and_catalog_vsam(ansible_zos_module, vo
789788
finally:
790789
hosts.all.zos_data_set(name=default_data_set_name, state="absent")
791790

791+
def test_creation_conflict_same_name_diff_volume(ansible_zos_module, volumes_on_systems):
792+
volumes = Volume_Handler(volumes_on_systems)
793+
volume_1 = volumes.get_available_vol()
794+
volume_2 = volumes.get_available_vol()
795+
assert volume_1 != volume_2, "Need two different volumes for this test"
796+
797+
hosts = ansible_zos_module
798+
data_set_name = get_tmp_ds_name()
799+
try:
800+
# Step 1: Create PDS on volume_1
801+
results = hosts.all.zos_data_set(
802+
name=data_set_name,
803+
state="present",
804+
type="pds",
805+
volumes=[volume_1]
806+
)
807+
for result in results.contacted.values():
808+
assert result.get("changed") is True
809+
results = hosts.all.zos_data_set(
810+
name=data_set_name,
811+
state="present",
812+
type="pds",
813+
volumes=[volume_2]
814+
)
815+
for result in results.contacted.values():
816+
assert result.get("failed") is True
817+
assert "datasetcatalogedondifferentvolumeerror" in result.get("msg", "").lower()
818+
finally:
819+
# Cleanup
820+
hosts.all.zos_data_set(name=data_set_name, state="absent")
792821

793822
def test_data_set_temp_data_set_name(ansible_zos_module):
794823
try:

0 commit comments

Comments
 (0)