Source code for saltext.sap_car._states.sap_car
"""
SaltStack extension for SAPCAR
Copyright (C) 2022 SAP UCC Magdeburg
SAPCAR States
=============
States to manage SAPCAR archives
:codeauthor: Benjamin Wegener
:maturity: new
:depends: N/A
:platform: Linux
This module can be used to ensure that files from a SAPCAR archive are extracted. The state
``extracted`` will check for file existance based on the list of files in the archive, but
NOT based on content or hash!
.. code-block:: jinja
SAProuter is extracted:
sap_car.extracted:
- name: /mnt/nfs/saprouter.sar
- output_dir: /usr/sap/saprouter/
- user: root
- group: root
- require:
- pkg: SAPCAR is installed
.. note::
Even though there are no python dependencies, SAPCAR must be available in the PATH.
For more information on SAPCAR, see http://www.easymarketplace.de/SAPCAR.php.
"""
import logging
import salt.utils.files
# Globals
log = logging.getLogger(__name__)
__virtualname__ = "sap_car"
[docs]def __virtual__():
"""
Only works on Linux and if SAPCAR is available in PATH
"""
if "sap_car.list" not in __salt__:
return (
False,
"The sap_car execution module failed to load.",
)
return __virtualname__
[docs]def extracted(name, options=None, output_dir=None, user=None, group=None):
"""
Extracts a SAPCAR archive if necessary.
name
Path to the sar file to be extracted
options
Additional options to SAPCAR command
output_dir
Directory where archive will be extracted. It creates the dir if the path doesn't exist. If
it's not set the current dir is used
user
User to execute the SAPCAR command
group
Group to execute
"""
log.debug(f"Running function with name={name}")
ret = {
"name": name,
"changes": {"old": [], "new": []},
"result": True if not __opts__["test"] else None,
"comment": "",
}
log.debug("Listing files of archive")
archive_file_list = __salt__["sap_car.list"](path=name, user=user, group=group)
if not isinstance(archive_file_list, list):
log.error("An error occured during list of files")
ret["comment"] = "An error occured during list of files, check the log files"
ret["result"] = False
return ret
log.debug("Listing files of target dir")
disk_file_list = salt.utils.files.list_files(output_dir) # returns full paths
disk_file_list.remove(output_dir) # is part of list by default
disk_file_list = [x.replace(output_dir, "") for x in disk_file_list]
log.debug("Checking if files need to be extracted")
files_to_extract = []
for archive_file in archive_file_list:
if archive_file not in disk_file_list:
files_to_extract.append(archive_file)
else:
disk_file_list.remove(archive_file) # should increase performance for large archives
if not files_to_extract:
log.debug("All files are already extracted")
ret["comment"] = "All files are already extracted"
ret["result"] = True
ret["changes"] = {}
return ret
if files_to_extract == archive_file_list:
log.debug("All files need to be extracted")
files_to_extract = None
log.debug("Extracting files")
if __opts__["test"]:
ret["comment"] = f"Extracted archive {name} to {output_dir}"
if files_to_extract:
ret["changes"]["new"] = f"Would extract the following files:\n{files_to_extract}"
else:
ret["changes"]["new"] = f"Would extract all files from {name}"
ret["result"] = None
else:
result = __salt__["sap_car.extract"](
path=name,
files=files_to_extract,
options=options,
output_dir=output_dir,
user=user,
group=group,
)
if not isinstance(result, bool):
log.error(f"An error occured during execution:\n{result}")
ret["comment"] = "An error occured during execution, check the log files"
ret["result"] = False
return ret
if not result:
log.error(f"Could not extract archive {name}")
ret["comment"] = f"Could not extract archive {name}"
ret["result"] = False
else:
ret["comment"] = f"Extracted archive {name} to {output_dir}"
if files_to_extract:
ret["changes"]["new"] = files_to_extract
else:
ret["changes"]["new"] = f"Extracted all files from {name}"
ret["result"] = True
if not ret["changes"]["new"]:
del ret["changes"]["new"]
if not ret["changes"]["old"]:
del ret["changes"]["old"]
log.debug(f"Returning:\n{ret}")
return ret