306
306
type: bool
307
307
default: false
308
308
required: false
309
-
309
+ encoding:
310
+ description:
311
+ - Specifies the character encoding conversion to be applied to the
312
+ source files before archiving.
313
+ - Supported character sets rely on the charset conversion utility
314
+ C(iconv) version the most common character sets are supported.
315
+ - After conversion the files are stored in same location and name
316
+ as src and the same src is taken in consideration for archive.
317
+ - Source files will be converted to the new encoding and will not
318
+ be restored to their original encoding.
319
+ - If encoding fails for any file in a set of multiple files, an
320
+ exception will be raised and archiving will be skipped.
321
+ type: dict
322
+ required: false
323
+ suboptions:
324
+ from:
325
+ description:
326
+ - The character set of the source I(src).
327
+ required: false
328
+ type: str
329
+ to:
330
+ description:
331
+ - The destination I(dest) character set for the files to be written as.
332
+ required: false
333
+ type: str
310
334
attributes:
311
335
action:
312
336
support: none
404
428
name: terse
405
429
format_options:
406
430
use_adrdssu: true
431
+
432
+ - name: Encode the source data set into Latin-1 before archiving into a terse data set
433
+ zos_archive:
434
+ src: "USER.ARCHIVE.TEST"
435
+ dest: "USER.ARCHIVE.RESULT.TRS"
436
+ format:
437
+ name: terse
438
+ encoding:
439
+ from: IBM-1047
440
+ to: ISO8859-1
407
441
'''
408
442
409
443
RETURN = r'''
465
499
from ansible .module_utils ._text import to_bytes
466
500
from ansible .module_utils .basic import AnsibleModule
467
501
from ansible_collections .ibm .ibm_zos_core .plugins .module_utils import (
468
- better_arg_parser , data_set , mvs_cmd , validation )
502
+ better_arg_parser , data_set , mvs_cmd , validation , encode )
469
503
from ansible_collections .ibm .ibm_zos_core .plugins .module_utils .import_handler import \
470
504
ZOAUImportError
471
505
@@ -618,6 +652,7 @@ def __init__(self, module):
618
652
The state of the input C(src).
619
653
xmit_log_data_set : str
620
654
The name of the data set to store xmit log output.
655
+
621
656
"""
622
657
self .module = module
623
658
self .dest = module .params ['dest' ]
@@ -637,6 +672,9 @@ def __init__(self, module):
637
672
self .dest_state = STATE_ABSENT
638
673
self .state = STATE_PRESENT
639
674
self .xmit_log_data_set = ""
675
+ encoding_param = module .params .get ("encoding" ) or {}
676
+ self .from_encoding = encoding_param .get ("from" )
677
+ self .to_encoding = encoding_param .get ("to" )
640
678
641
679
def targets_exist (self ):
642
680
"""Returns if there are targets or not.
@@ -684,6 +722,10 @@ def remove_targets(self):
684
722
def compute_dest_size (self ):
685
723
pass
686
724
725
+ @abc .abstractmethod
726
+ def encode_source (self ):
727
+ pass
728
+
687
729
@property
688
730
def result (self ):
689
731
"""Returns a dict with the results.
@@ -906,6 +948,21 @@ def get_state(self):
906
948
if bool (self .not_found ):
907
949
self .dest_state = STATE_INCOMPLETE
908
950
951
+ def encode_source (self ):
952
+ """Convert encoding for given src
953
+ """
954
+ enc_utils = encode .EncodeUtils ()
955
+ try :
956
+ for target in self .targets :
957
+ convert_rc = enc_utils .uss_convert_encoding_prev (
958
+ target , target , self .from_encoding , self .to_encoding
959
+ )
960
+ if convert_rc :
961
+ enc_utils .uss_tag_encoding (target , self .to_encoding )
962
+
963
+ except Exception as e :
964
+ raise EncodeError ("Failed to encode in the required codeset: {e}" ) from e
965
+
909
966
910
967
class TarArchive (USSArchive ):
911
968
def __init__ (self , module ):
@@ -1372,6 +1429,28 @@ def compute_dest_size(self):
1372
1429
dest_space = math .ceil (dest_space / 1024 )
1373
1430
self .dest_data_set .update (space_primary = dest_space , space_type = "k" )
1374
1431
1432
+ def encode_source (self ):
1433
+ """Convert encoding for given src
1434
+ """
1435
+ enc_utils = encode .EncodeUtils ()
1436
+
1437
+ try :
1438
+ for target in self .targets :
1439
+ ds_type = data_set .DataSetUtils (target , tmphlq = self .tmphlq ).ds_type ()
1440
+ if not ds_type :
1441
+ raise EncodeError ("Unable to determine data set type of {0}" .format (target ))
1442
+ enc_utils .mvs_convert_encoding (
1443
+ target ,
1444
+ target ,
1445
+ self .from_encoding ,
1446
+ self .to_encoding ,
1447
+ src_type = ds_type ,
1448
+ dest_type = ds_type ,
1449
+ tmphlq = self .tmphlq
1450
+ )
1451
+ except Exception as e :
1452
+ raise EncodeError (f"Failed to encode in the required codeset: { e } " ) from e
1453
+
1375
1454
1376
1455
class AMATerseArchive (MVSArchive ):
1377
1456
def __init__ (self , module ):
@@ -1604,6 +1683,24 @@ def get_error_hint(self, output):
1604
1683
return msg .format (sys_abend , reason_code , error_hint )
1605
1684
1606
1685
1686
+ class EncodeError (Exception ):
1687
+ def __init__ (self , message ):
1688
+ """Error during encoding.
1689
+
1690
+ Parameters
1691
+ ----------
1692
+ message : str
1693
+ Human readable string describing the exception.
1694
+
1695
+ Attributes
1696
+ ----------
1697
+ msg : str
1698
+ Human readable string describing the exception.
1699
+ """
1700
+ self .msg = 'An error occurred during encoding: "{0}"' .format (message )
1701
+ super (EncodeError , self ).__init__ (self .msg )
1702
+
1703
+
1607
1704
def run_module ():
1608
1705
"""Initialize module.
1609
1706
@@ -1686,7 +1783,21 @@ def run_module():
1686
1783
)
1687
1784
),
1688
1785
tmp_hlq = dict (type = 'str' ),
1689
- force = dict (type = 'bool' , default = False )
1786
+ force = dict (type = 'bool' , default = False ),
1787
+ encoding = dict (
1788
+ type = 'dict' ,
1789
+ required = False ,
1790
+ options = {
1791
+ 'from' : dict (
1792
+ type = 'str' ,
1793
+ required = False ,
1794
+ ),
1795
+ "to" : dict (
1796
+ type = 'str' ,
1797
+ required = False ,
1798
+ )
1799
+ }
1800
+ )
1690
1801
),
1691
1802
supports_check_mode = True ,
1692
1803
)
@@ -1761,7 +1872,14 @@ def run_module():
1761
1872
)
1762
1873
),
1763
1874
tmp_hlq = dict (type = 'qualifier_or_empty' , default = '' ),
1764
- force = dict (type = 'bool' , default = False )
1875
+ force = dict (type = 'bool' , default = False ),
1876
+ encoding = dict (
1877
+ type = 'dict' ,
1878
+ options = {
1879
+ 'from' : dict (type = 'str' ),
1880
+ "to" : dict (type = 'str' )
1881
+ }
1882
+ )
1765
1883
)
1766
1884
1767
1885
result = dict (
@@ -1779,13 +1897,16 @@ def run_module():
1779
1897
except ValueError as err :
1780
1898
module .fail_json (msg = "Parameter verification failed" , stderr = str (err ))
1781
1899
1900
+ encoding = parsed_args .get ("encoding" )
1782
1901
archive = get_archive_handler (module )
1783
1902
1784
1903
if archive .dest_exists () and not archive .force :
1785
1904
module .fail_json (msg = "%s file exists. Use force flag to replace dest" % archive .dest )
1786
1905
1787
1906
archive .find_targets ()
1788
1907
if archive .targets_exist ():
1908
+ if encoding :
1909
+ archive .encode_source ()
1789
1910
archive .compute_dest_size ()
1790
1911
archive .archive_targets ()
1791
1912
if archive .remove :
0 commit comments