Source code for saltext.sap_likey._states.sap_likey

"""
SaltStack extension for saplikey
Copyright (C) 2022 SAP UCC Magdeburg

SAP NetWeaver AS ABAP License Key state module
==============================================
SaltStack module that implements states based on ``saplikey`` functionality.

:codeauthor:    Benjamin Wegener, Alexander Wilke
:maturity:      new
:depends:       requests
:platform:      Linux

This module implements states that utilize ``saplikey`` functionality. The command line tool is
part of the SAP NetWeaver AS ABAP Kernel and allows license key management from the command line.

.. note::
    This module can only run on linux platforms.
"""
import logging


# Globals
log = logging.getLogger(__name__)

__virtualname__ = "sap_likey"


# pylint: disable=unused-argument
[docs]def license_present(name, filename=None, remove_other_sid=True, remove_other_hwkey=True, **kwargs): """ Ensure that the license keys defined in a file are present in the system. name SID of the SAP system. filename Full path to the license file, default is None. If no filename is given, a temporary license will be installed if no valid license is present in the system. remove_other_sid Remove licenses that are not assigned to the SID (default is ``True``). remove_other_hwkey Remove licenses that are not assigned to the current hardware key (default is ``True``). Example: .. code-block:: jinja License for SAP System S4H is installed: sap_likey.license_present: - name: S4H - filename: /tmp/S4H.txt """ log.debug("Running function") ret = {"name": name, "changes": {"old": [], "new": []}, "comment": "", "result": True} log.debug("Retrieving system info") info = __salt__["sap_likey.info"](sid=name) log.debug("Retrieving installed licenses") licenses_system = __salt__["sap_likey.show"](sid=name) if remove_other_sid: log.debug(f"Removing licenses not assigned to {name}") for lic in licenses_system: if lic["system"] != name: log.debug(f"Found license assigned to {lic['system']}, removing") if __opts__["test"]: msg = ( f"SAP system license {lic['system']} / " f"{lic['hardware_key']} / {lic['software_product']} would be removed" ) ret["changes"]["old"].append(msg) else: success = __salt__["sap_likey.delete"](name=lic["system"], sid=name) if success: msg = ( f"SAP system license {lic['system']} / " f"{lic['hardware_key']} / {lic['software_product']}" ) ret["changes"]["old"].append(msg) else: ret["comment"] = ( f"Could not remove license for SAP system license {lic['system']} " f"/ {lic['hardware_key']} / {lic['software_product']}" ) ret["result"] = False return ret if remove_other_hwkey: log.debug(f"Removing licenses not assigned to hardware_key {info['hardware_key']}") for lic in licenses_system: if lic["hardware_key"] != info["hardware_key"]: log.debug(f"Found license assigned to {lic['hardware_key']}, removing") if __opts__["test"]: msg = ( f"SAP system license {lic['system']} / {lic['hardware_key']} " f"/ {lic['software_product']} would be removed" ) ret["changes"]["old"].append(msg) else: success = __salt__["sap_likey.delete"]( name=lic["system"], sid=name, hwkey=lic["hardware_key"] ) if success: msg = ( f"SAP system license {lic['system']} / {lic['hardware_key']} " f"/ {lic['software_product']}" ) ret["changes"]["old"].append(msg) else: ret["comment"] = ( f"Could not remove license for system {lic['system']} / {lic['hardware_key']} " f"/ {lic['software_product']}" ) ret["result"] = False return ret if filename: log.debug(f"Reading license file {filename}") licenses_file = __salt__["sap_likey.read_lic_file"](filename=filename) # because there can be multiple licenses in one file, we need to check if ALL match all_valid = len(licenses_file) > 0 for lic_file in licenses_file: found = False for lic_sys in licenses_system: # removing attributes that are not present in the license from file if "last_successful_check" in lic_sys: del lic_sys["last_successful_check"] if "validity" in lic_sys: del lic_sys["validity"] if "type_of_license_key" in lic_sys: del lic_sys["type_of_license_key"] if lic_file == lic_sys: found = True break if not found: all_valid = False break if not all_valid: log.debug(f"Not all licenses are installed, removing all licenses for {name}") if __opts__["test"]: for lic in licenses_system: msg = ( f"SAP system license {lic['system']} / {lic['hardware_key']} " f"/ {lic['software_product']} would be removed" ) ret["changes"]["old"].append(msg) else: success = __salt__["sap_likey.delete"](name=name, sid=name) if success: for lic in licenses_system: msg = ( f"SAP system license {lic['system']} / " f"{lic['hardware_key']} / {lic['software_product']}" ) ret["changes"]["old"].append(msg) else: ret["comment"] = f"Could not remove license for system {name}" ret["result"] = False return ret # checking if the <sid>adm user can read the license file sidadm = f"{name.lower()}adm" if __salt__["file.get_user"](filename) != sidadm: log.debug(f"Ensuring that {sidadm} owns the license file") user_info = __salt__["user.info"](sidadm) if __opts__["test"]: msg = ( f"Would change to owner of {filename} to uid {user_info['uid']} " f"/ gid {user_info['gid']}" ) ret["changes"]["new"].append(msg) else: __salt__["file.chown"]( user=user_info["uid"], group=user_info["gid"], path=filename ) log.debug("Installing new licenses") if __opts__["test"]: for lic in licenses_file: msg = ( f"SAP system license {lic['system']} / {lic['hardware_key']} " f"/ {lic['software_product']} would be installed" ) ret["changes"]["new"].append(msg) else: success = __salt__["sap_likey.install"](sid=name, filename=filename) if success: for lic in licenses_file: msg = ( f"SAP system license {lic['system']} / " f"{lic['hardware_key']} / {lic['software_product']}" ) ret["changes"]["new"].append(msg) else: ret["comment"] = f"Could not install licenses for system {name}" ret["result"] = False return ret ret["comment"] = "Installed licenses" else: log.debug("All licenses are already installed correctly") else: log.debug("No license file defined, checking for a valid license and removing all others") valid_license = False for lic in licenses_system: # skip maintenance licenses if lic["software_product"].startswith("Maintenance_"): continue if lic["validity"] == "valid": valid_license = True break if not valid_license: if licenses_system: msg = "No valid license defined, removing all licenses and adding temporary one" log.debug(msg) if __opts__["test"]: ret["changes"]["old"].append(f"SAP system {name} license would be deleted") else: success = __salt__["sap_likey.delete"](name=name, sid=name) if success: ret["changes"]["old"].append(f"SAP system {name} license") else: ret["comment"] = f"Could not remove license for system {name}" ret["result"] = False return ret log.debug(f"Adding temporary license for {info['software_products']}") if __opts__["test"]: msg = ( f"SAP system {name} temporary license for {info['software_products']} " "would be added" ) ret["changes"]["new"].append(msg) else: success = __salt__["sap_likey.temp"](sid=name, product=info["software_products"]) if success: msg = f"SAP system {name} temporary license for {info['software_products']}" ret["changes"]["new"].append(msg) else: ret["comment"] = ( f"Could not add temporay license for system {name} " f"for {info['software_products']}" ) ret["result"] = False return ret else: ret["comment"] = f"System {name} already has a valid license" if not ret["changes"].get("new") and not ret["changes"].get("old"): ret["changes"] = {} ret["comment"] = "No changes required" ret["result"] = True if (not __opts__["test"] or not ret["changes"]) else None return ret
# pylint: disable=unused-argument
[docs]def license_absent(name, remove_all=True, **kwargs): """ Ensure that a SAP license is absent from an SAP system. name SID of the SAP system. remove_all Set to True to remove all licenses, default is ``True``. Example: .. code-block:: jinja All licenses for SAP System S4H are absent: sap_likey.license_absent: - name: S4H - remove_all: True """ log.debug("Running function") ret = {"name": name, "changes": {"old": [], "new": []}, "comment": "", "result": True} licenses_system = __salt__["sap_likey.show"](sid=name) for lic_sys in licenses_system: if remove_all or lic_sys["system"] == name: log.debug(f"Removing license for {lic_sys['system']}") if __opts__["test"]: msg = ( f"SAP system license {lic_sys['system']} / {lic_sys['hardware_key']} " f"/ {lic_sys['software_product']} would be removed" ) ret["changes"]["old"].append(msg) else: success = __salt__["sap_likey.delete"]( name=name, sid=name, hwkey=lic_sys["hardware_key"], product=lic_sys["software_product"], ) if success: msg = ( f"SAP system license {lic_sys['system']} / {lic_sys['hardware_key']} " f"/ {lic_sys['software_product']}" ) ret["changes"]["old"].append(msg) else: ret["comment"] = ( f"Could not remove license for {lic_sys['system']} / " f"{lic_sys['hardware_key']} / {lic_sys['software_product']}" ) ret["result"] = False return ret if not ret["changes"].get("new") and not ret["changes"].get("old"): ret["changes"] = {} ret["comment"] = "No changes required" ret["result"] = True if (not __opts__["test"] or not ret["changes"]) else None return ret