48
48
suboptions:
49
49
name:
50
50
description:
51
- - The compression format to use .
51
+ - The compression format used while archiving .
52
52
type: str
53
53
required: true
54
54
choices:
78
78
type: str
79
79
use_adrdssu:
80
80
description:
81
- - If set to true, the C(zos_archive ) module will use Data
81
+ - If set to true, the C(zos_unarchive ) module will use Data
82
82
Facility Storage Management Subsystem data set services
83
83
(DFSMSdss) program ADRDSSU to uncompress data sets from
84
84
a portable format after using C(xmit) or C(terse).
312
312
type: bool
313
313
required: false
314
314
default: false
315
-
315
+ encoding:
316
+ description:
317
+ - Specifies the character encoding conversion to be applied to the
318
+ destination files after unarchiving.
319
+ - Supported character sets rely on the charset conversion utility
320
+ C(iconv) version the most common character sets are supported.
321
+ - After conversion the files are stored in same location as they
322
+ were unarchived to under the same original name. No backup of the
323
+ original unconverted files is there as for that unarchive can be
324
+ executed again without encoding params on same source archive files.
325
+ - Destination files will be converted to the new encoding and will not
326
+ be restored to their original encoding.
327
+ - If encoding fails for any file in a set of multiple files, an
328
+ exception will be raised and the name of the file skipped will be
329
+ provided completing the task successfully with rc code 0.
330
+ - Encoding does not check if the file is already present or not.
331
+ It works on the file/files successfully unarchived.
332
+ type: dict
333
+ required: false
334
+ suboptions:
335
+ from:
336
+ description:
337
+ - The character set of the source I(src).
338
+ required: false
339
+ type: str
340
+ to:
341
+ description:
342
+ - The destination I(dest) character set for the files to be written as.
343
+ required: false
344
+ type: str
316
345
attributes:
317
346
action:
318
347
support: full
380
409
format_options:
381
410
use_adrdssu: true
382
411
list: true
412
+
413
+ # Encoding example
414
+ - name: Encode the destination data set into Latin-1 after unarchiving.
415
+ zos_unarchive:
416
+ src: "USER.ARCHIVE.RESULT.TRS"
417
+ format:
418
+ name: terse
419
+ encoding:
420
+ from: IBM-1047
421
+ to: ISO8859-1
383
422
'''
384
423
385
424
RETURN = r'''
404
443
Any files or data sets not found during extraction.
405
444
type: str
406
445
returned: success
446
+ encoded:
447
+ description:
448
+ List of files or data sets that were successfully encoded.
449
+ type: list
450
+ returned: success
451
+ failed_on_encoding:
452
+ description:
453
+ List of files or data sets that were failed while encoding.
454
+ type: list
455
+ returned: success
456
+
407
457
'''
408
458
409
459
import abc
412
462
better_arg_parser ,
413
463
data_set ,
414
464
validation ,
415
- mvs_cmd )
465
+ mvs_cmd ,
466
+ encode )
416
467
import re
417
468
import os
418
469
import zipfile
@@ -470,6 +521,10 @@ def __init__(self, module):
470
521
Paths that were on include, but are missing from the files in archive.
471
522
remote_src : bool
472
523
If the source is remote or not.
524
+ from_encoding: str
525
+ The encoding of the source file.
526
+ to_encoding: str
527
+ The required encoding of the destination file.
473
528
"""
474
529
self .module = module
475
530
self .src = module .params .get ("src" )
@@ -485,8 +540,13 @@ def __init__(self, module):
485
540
self .changed = False
486
541
self .missing = list ()
487
542
self .remote_src = module .params .get ("remote_src" )
543
+ encoding_param = module .params .get ("encoding" ) or {}
544
+ self .from_encoding = encoding_param .get ("from" )
545
+ self .to_encoding = encoding_param .get ("to" )
488
546
if self .dest == '' :
489
547
self .dest = os .path .dirname (self .src )
548
+ self .encoded = list ()
549
+ self .failed_on_encoding = list ()
490
550
491
551
@abc .abstractmethod
492
552
def extract_src (self ):
@@ -531,6 +591,35 @@ def update_permissions(self):
531
591
file_args = self .module .load_file_common_arguments (self .module .params , path = file_name )
532
592
self .module .set_fs_attributes_if_different (file_args , self .changed )
533
593
594
+ def encode_destination (self ):
595
+ """Convert encoding for given destination
596
+ Returns
597
+ -------
598
+ Union
599
+ encoded or failed_on_encoding list
600
+ """
601
+ enc_utils = encode .EncodeUtils ()
602
+ self .encoded = []
603
+ self .failed_on_encoding = []
604
+
605
+ for target in self .targets :
606
+ try :
607
+ file_path = os .path .normpath (os .path .join (self .dest , target ))
608
+ convert_rc = enc_utils .uss_convert_encoding_prev (
609
+ file_path , file_path , self .from_encoding , self .to_encoding
610
+ )
611
+ if convert_rc :
612
+ enc_utils .uss_tag_encoding (file_path , self .to_encoding )
613
+ self .encoded .append (os .path .abspath (target ))
614
+
615
+ except Exception :
616
+ self .failed_on_encoding .append (os .path .abspath (target ))
617
+
618
+ return {
619
+ "encoded" : self .encoded ,
620
+ "failed_on_encoding" : self .failed_on_encoding
621
+ }
622
+
534
623
@property
535
624
def result (self ):
536
625
"""Result.
@@ -545,6 +634,8 @@ def result(self):
545
634
'changed' : self .changed ,
546
635
'targets' : self .targets ,
547
636
'missing' : self .missing ,
637
+ 'encoded' : getattr (self , 'encoded' , []),
638
+ 'failed_on_encoding' : getattr (self , 'failed_on_encoding' , []),
548
639
}
549
640
550
641
def extract_all (self , members ):
@@ -1050,6 +1141,8 @@ def extract_src(self):
1050
1141
if not self .use_adrdssu :
1051
1142
temp_ds , rc = self ._create_dest_data_set (** self .dest_data_set )
1052
1143
rc = self .unpack (self .src , temp_ds )
1144
+ self .targets = [temp_ds ]
1145
+
1053
1146
else :
1054
1147
temp_ds , rc = self ._create_dest_data_set (type = "seq" ,
1055
1148
record_format = "u" ,
@@ -1108,6 +1201,40 @@ def clean_environment(self, data_sets=None, uss_files=None, remove_targets=False
1108
1201
for target in self .targets :
1109
1202
data_set .DataSet .ensure_absent (target )
1110
1203
1204
+ def encode_destination (self ):
1205
+ """Convert encoding for given destination
1206
+ Returns
1207
+ -------
1208
+ Union
1209
+ encoded or failed_on_encoding list
1210
+ """
1211
+ enc_utils = encode .EncodeUtils ()
1212
+ self .encoded = []
1213
+ self .failed_on_encoding = []
1214
+
1215
+ for target in self .targets :
1216
+ try :
1217
+ ds_utils = data_set .DataSetUtils (target , tmphlq = self .tmphlq )
1218
+ ds_type = ds_utils .ds_type ()
1219
+ if not ds_type :
1220
+ ds_type = "PS"
1221
+ enc_utils .mvs_convert_encoding (
1222
+ target ,
1223
+ target ,
1224
+ self .from_encoding ,
1225
+ self .to_encoding ,
1226
+ src_type = ds_type ,
1227
+ dest_type = ds_type ,
1228
+ tmphlq = self .tmphlq
1229
+ )
1230
+ self .encoded .append (os .path .abspath (target ))
1231
+ except Exception :
1232
+ self .failed_on_encoding .append (os .path .abspath (target ))
1233
+ return {
1234
+ "encoded" : self .encoded ,
1235
+ "failed_on_encoding" : self .failed_on_encoding
1236
+ }
1237
+
1111
1238
1112
1239
class AMATerseUnarchive (MVSUnarchive ):
1113
1240
def __init__ (self , module ):
@@ -1379,6 +1506,24 @@ def __init__(self, tarinfo, path):
1379
1506
super ().__init__ ()
1380
1507
1381
1508
1509
+ class EncodeError (Exception ):
1510
+ def __init__ (self , message ):
1511
+ """Error during encoding.
1512
+
1513
+ Parameters
1514
+ ----------
1515
+ message : str
1516
+ Human readable string describing the exception.
1517
+
1518
+ Attributes
1519
+ ----------
1520
+ msg : str
1521
+ Human readable string describing the exception.
1522
+ """
1523
+ self .msg = 'An error occurred during encoding: "{0}"' .format (message )
1524
+ super (EncodeError , self ).__init__ (self .msg )
1525
+
1526
+
1382
1527
def run_module ():
1383
1528
"""Initialize module.
1384
1529
Raises
@@ -1467,6 +1612,20 @@ def run_module():
1467
1612
tmp_hlq = dict (type = 'str' ),
1468
1613
force = dict (type = 'bool' , default = False ),
1469
1614
remote_src = dict (type = 'bool' , default = False ),
1615
+ encoding = dict (
1616
+ type = 'dict' ,
1617
+ required = False ,
1618
+ options = {
1619
+ 'from' : dict (
1620
+ type = 'str' ,
1621
+ required = False ,
1622
+ ),
1623
+ "to" : dict (
1624
+ type = 'str' ,
1625
+ required = False ,
1626
+ )
1627
+ }
1628
+ ),
1470
1629
),
1471
1630
mutually_exclusive = [
1472
1631
['include' , 'exclude' ],
@@ -1543,6 +1702,13 @@ def run_module():
1543
1702
mutually_exclusive = [
1544
1703
['include' , 'exclude' ],
1545
1704
],
1705
+ encoding = dict (
1706
+ type = 'dict' ,
1707
+ options = {
1708
+ 'from' : dict (type = 'str' ),
1709
+ "to" : dict (type = 'str' )
1710
+ }
1711
+ ),
1546
1712
)
1547
1713
1548
1714
try :
@@ -1565,6 +1731,14 @@ def run_module():
1565
1731
if unarchive .dest_unarchived () and unarchive .dest_type () == "USS" :
1566
1732
unarchive .update_permissions ()
1567
1733
1734
+ encoding = parsed_args .get ("encoding" )
1735
+ if unarchive .dest_unarchived () and encoding :
1736
+ encoding_result = unarchive .encode_destination ()
1737
+ unarchive .result .update ({
1738
+ "encoded" : encoding_result .get ("encoded" , []),
1739
+ "failed_on_encoding" : encoding_result .get ("failed_on_encoding" , [])
1740
+ })
1741
+
1568
1742
module .exit_json (** unarchive .result )
1569
1743
1570
1744
0 commit comments