PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/solarisipspkg.py |
""" IPS pkg support for Solaris .. important:: If you feel that Salt should be using this module to manage packages on a minion, and it is using a different module (or gives an error similar to *'pkg.install' is not available*), see :ref:`here <module-provider-override>`. This module provides support for Solaris 11 new package management - IPS (Image Packaging System). This is the default pkg module for Solaris 11 (and later). If you want to use also other packaging module (e.g. pkgutil) together with IPS, you need to override the ``pkg`` provider in sls for each package: .. code-block:: yaml mypackage: pkg.installed: - provider: pkgutil Or you can override it globally by setting the :conf_minion:`providers` parameter in your Minion config file like this: .. code-block:: yaml providers: pkg: pkgutil Or you can override it globally by setting the :conf_minion:`providers` parameter in your Minion config file like this: .. code-block:: yaml providers: pkg: pkgutil """ import copy import logging import salt.utils.data import salt.utils.functools import salt.utils.path import salt.utils.pkg from salt.exceptions import CommandExecutionError # Define the module's virtual name __virtualname__ = "pkg" log = logging.getLogger(__name__) def __virtual__(): """ Set the virtual pkg module if the os is Solaris 11 """ if ( __grains__["os_family"] == "Solaris" and float(__grains__["kernelrelease"]) > 5.10 and salt.utils.path.which("pkg") ): return __virtualname__ return ( False, "The solarisips execution module failed to load: only available " "on Solaris >= 11.", ) ips_pkg_return_values = { 0: "Command succeeded.", 1: "An error occurred.", 2: "Invalid command line options were specified.", 3: "Multiple operations were requested, but only some of them succeeded.", 4: "No changes were made - nothing to do.", 5: "The requested operation cannot be performed on a live image.", 6: ( "The requested operation cannot be completed because the licenses for " "the packages being installed or updated have not been accepted." ), 7: "The image is currently in use by another process and cannot be modified.", } def _ips_get_pkgname(line): """ Extracts package name from "pkg list -v" output. Input: one line of the command output Output: pkg name (e.g.: "pkg://solaris/x11/library/toolkit/libxt") Example use: line = "pkg://solaris/x11/library/toolkit/libxt@1.1.3,5.11-0.175.1.0.0.24.1317:20120904T180030Z i--" name = _ips_get_pkgname(line) """ return line.split()[0].split("@")[0].strip() def _ips_get_pkgversion(line): """ Extracts package version from "pkg list -v" output. Input: one line of the command output Output: package version (e.g.: "1.1.3,5.11-0.175.1.0.0.24.1317:20120904T180030Z") Example use: line = "pkg://solaris/x11/library/toolkit/libxt@1.1.3,5.11-0.175.1.0.0.24.1317:20120904T180030Z i--" name = _ips_get_pkgversion(line) """ return line.split()[0].split("@")[1].strip() def refresh_db(full=False, **kwargs): """ Updates the remote repos database. full : False Set to ``True`` to force a refresh of the pkg DB from all publishers, regardless of the last refresh time. CLI Example: .. code-block:: bash salt '*' pkg.refresh_db salt '*' pkg.refresh_db full=True """ # Remove rtag file to keep multiple refreshes from happening in pkg states salt.utils.pkg.clear_rtag(__opts__) if full: return __salt__["cmd.retcode"]("/bin/pkg refresh --full") == 0 else: return __salt__["cmd.retcode"]("/bin/pkg refresh") == 0 def upgrade_available(name, **kwargs): """ Check if there is an upgrade available for a certain package Accepts full or partial FMRI. Returns all matches found. CLI Example: .. code-block:: bash salt '*' pkg.upgrade_available apache-22 """ version = None cmd = ["pkg", "list", "-Huv", name] lines = __salt__["cmd.run_stdout"](cmd).splitlines() if not lines: return {} ret = {} for line in lines: ret[_ips_get_pkgname(line)] = _ips_get_pkgversion(line) return ret def list_upgrades(refresh=True, **kwargs): # pylint: disable=W0613 """ Lists all packages available for update. When run in global zone, it reports only upgradable packages for the global zone. When run in non-global zone, it can report more upgradable packages than ``pkg update -vn``, because ``pkg update`` hides packages that require newer version of ``pkg://solaris/entire`` (which means that they can be upgraded only from the global zone). If ``pkg://solaris/entire`` is found in the list of upgrades, then the global zone should be updated to get all possible updates. Use ``refresh=True`` to refresh the package database. refresh : True Runs a full package database refresh before listing. Set to ``False`` to disable running the refresh. .. versionchanged:: 2017.7.0 In previous versions of Salt, ``refresh`` defaulted to ``False``. This was changed to default to ``True`` in the 2017.7.0 release to make the behavior more consistent with the other package modules, which all default to ``True``. CLI Example: .. code-block:: bash salt '*' pkg.list_upgrades salt '*' pkg.list_upgrades refresh=False """ if salt.utils.data.is_true(refresh): refresh_db(full=True) upgrades = {} # awk is in core-os package so we can use it without checking lines = __salt__["cmd.run_stdout"]("/bin/pkg list -Huv").splitlines() for line in lines: upgrades[_ips_get_pkgname(line)] = _ips_get_pkgversion(line) return upgrades def upgrade(refresh=False, **kwargs): """ Upgrade all packages to the latest possible version. When run in global zone, it updates also all non-global zones. In non-global zones upgrade is limited by dependency constrains linked to the version of pkg://solaris/entire. Returns a dictionary containing the changes: .. code-block:: python {'<package>': {'old': '<old-version>', 'new': '<new-version>'}} When there is a failure, an explanation is also included in the error message, based on the return code of the ``pkg update`` command. CLI Example: .. code-block:: bash salt '*' pkg.upgrade """ if salt.utils.data.is_true(refresh): refresh_db() # Get a list of the packages before install so we can diff after to see # what got installed. old = list_pkgs() # Install or upgrade the package # If package is already installed cmd = ["pkg", "update", "-v", "--accept"] result = __salt__["cmd.run_all"](cmd, output_loglevel="trace", python_shell=False) __context__.pop("pkg.list_pkgs", None) new = list_pkgs() ret = salt.utils.data.compare_dicts(old, new) if result["retcode"] != 0: raise CommandExecutionError( "Problem encountered upgrading packages", info={ "changes": ret, "retcode": ips_pkg_return_values[result["retcode"]], "result": result, }, ) return ret def _list_pkgs_from_context(versions_as_list): """ Use pkg list from __context__ """ if versions_as_list: return __context__["pkg.list_pkgs"] else: ret = copy.deepcopy(__context__["pkg.list_pkgs"]) __salt__["pkg_resource.stringify"](ret) return ret def list_pkgs(versions_as_list=False, **kwargs): """ List the currently installed packages as a dict:: {'<package_name>': '<version>'} CLI Example: .. code-block:: bash salt '*' pkg.list_pkgs """ # not yet implemented or not applicable if any( [salt.utils.data.is_true(kwargs.get(x)) for x in ("removed", "purge_desired")] ): return {} if "pkg.list_pkgs" in __context__ and kwargs.get("use_context", True): return _list_pkgs_from_context(versions_as_list) ret = {} cmd = "/bin/pkg list -Hv" lines = __salt__["cmd.run_stdout"](cmd).splitlines() # column 1 is full FMRI name in form pkg://publisher/class/name@version for line in lines: name = _ips_get_pkgname(line) version = _ips_get_pkgversion(line) __salt__["pkg_resource.add_pkg"](ret, name, version) __salt__["pkg_resource.sort_pkglist"](ret) __context__["pkg.list_pkgs"] = copy.deepcopy(ret) if not versions_as_list: __salt__["pkg_resource.stringify"](ret) return ret def version(*names, **kwargs): """ Common interface for obtaining the version of installed packages. Accepts full or partial FMRI. If called using pkg_resource, full FMRI is required. Partial FMRI is returned if the package is not installed. CLI Example: .. code-block:: bash salt '*' pkg.version vim salt '*' pkg.version foo bar baz salt '*' pkg_resource.version pkg://solaris/entire """ if not names: return "" cmd = ["/bin/pkg", "list", "-Hv"] cmd.extend(names) lines = __salt__["cmd.run_stdout"](cmd, ignore_retcode=True).splitlines() ret = {} for line in lines: ret[_ips_get_pkgname(line)] = _ips_get_pkgversion(line) # Append package names which are not installed/found for name in names: if name not in ret: ret[name] = "" # Return a string if only one package name passed if len(names) == 1: try: return next(iter(ret.values())) except StopIteration: return "" return ret def latest_version(*names, **kwargs): """ The available version of packages in the repository. Accepts full or partial FMRI. Partial FMRI is returned if the full FMRI could not be resolved. If the latest version of a given package is already installed, an empty string will be returned for that package. Please use pkg.latest_version as pkg.available_version is being deprecated. .. versionchanged:: 2019.2.0 Support for multiple package names added. CLI Example: .. code-block:: bash salt '*' pkg.latest_version bash salt '*' pkg.latest_version pkg://solaris/entire salt '*' pkg.latest_version postfix sendmail """ if not names: return "" cmd = ["/bin/pkg", "list", "-Hnv"] cmd.extend(names) lines = __salt__["cmd.run_stdout"](cmd, ignore_retcode=True).splitlines() ret = {} for line in lines: ret[_ips_get_pkgname(line)] = _ips_get_pkgversion(line) installed = version(*names) if len(names) == 1: # Convert back our result in a dict if only one name is passed installed = {list(ret)[0] if ret else names[0]: installed} for name in ret: if name not in installed: continue if ret[name] == installed[name]: ret[name] = "" # Append package names which are not found for name in names: if name not in ret: ret[name] = "" # Return a string if only one package name passed if len(names) == 1: try: return next(iter(ret.values())) except StopIteration: return "" return ret # available_version is being deprecated available_version = salt.utils.functools.alias_function( latest_version, "available_version" ) def get_fmri(name, **kwargs): """ Returns FMRI from partial name. Returns empty string ('') if not found. In case of multiple match, the function returns list of all matched packages. CLI Example: .. code-block:: bash salt '*' pkg.get_fmri bash """ if name.startswith("pkg://"): # already full fmri return name cmd = ["/bin/pkg", "list", "-aHv", name] # there can be more packages matching the name lines = __salt__["cmd.run_stdout"](cmd).splitlines() if not lines: # empty string = package not found return "" ret = [] for line in lines: ret.append(_ips_get_pkgname(line)) return ret def normalize_name(name, **kwargs): """ Internal function. Normalizes pkg name to full FMRI before running pkg.install. In case of multiple matches or no match, it returns the name without modifications. CLI Example: .. code-block:: bash salt '*' pkg.normalize_name vim """ if name.startswith("pkg://"): # already full fmri return name cmd = ["/bin/pkg", "list", "-aHv", name] # there can be more packages matching the name lines = __salt__["cmd.run_stdout"](cmd).splitlines() # if we get more lines, it's multiple match (name not unique) # if we get zero lines, pkg is not installed # in both ways it's safer to return original (unmodified) name and let "pkg install" to deal with it if len(lines) != 1: return name # return pkg name return _ips_get_pkgname(lines[0]) def is_installed(name, **kwargs): """ Returns True if the package is installed. Otherwise returns False. Name can be full or partial FMRI. In case of multiple match from partial FMRI name, it returns True. CLI Example: .. code-block:: bash salt '*' pkg.is_installed bash """ cmd = ["/bin/pkg", "list", "-Hv", name] return __salt__["cmd.retcode"](cmd) == 0 def search(name, versions_as_list=False, **kwargs): """ Searches the repository for given pkg name. The name can be full or partial FMRI. All matches are printed. Globs are also supported. CLI Example: .. code-block:: bash salt '*' pkg.search bash """ ret = {} cmd = ["/bin/pkg", "list", "-aHv", name] out = __salt__["cmd.run_all"](cmd, ignore_retcode=True) if out["retcode"] != 0: # error = nothing found return {} # no error, processing pkg listing # column 1 is full FMRI name in form pkg://publisher/pkg/name@version for line in out["stdout"].splitlines(): name = _ips_get_pkgname(line) version = _ips_get_pkgversion(line) __salt__["pkg_resource.add_pkg"](ret, name, version) if not versions_as_list: __salt__["pkg_resource.stringify"](ret) return ret def install(name=None, refresh=False, pkgs=None, version=None, test=False, **kwargs): """ Install the named package using the IPS pkg command. Accepts full or partial FMRI. Returns a dict containing the new package names and versions:: {'<package>': {'old': '<old-version>', 'new': '<new-version>'}} Multiple Package Installation Options: pkgs A list of packages to install. Must be passed as a python list. CLI Example: .. code-block:: bash salt '*' pkg.install vim salt '*' pkg.install pkg://solaris/editor/vim salt '*' pkg.install pkg://solaris/editor/vim refresh=True salt '*' pkg.install pkgs='["foo", "bar"]' """ if not pkgs: if is_installed(name): return {} if refresh: refresh_db(full=True) pkg2inst = "" if pkgs: # multiple packages specified pkg2inst = [] for pkg in pkgs: if getattr(pkg, "items", False): if list(pkg.items())[0][1]: # version specified pkg2inst.append( f"{list(pkg.items())[0][0]}@{list(pkg.items())[0][1]}" ) else: pkg2inst.append(list(pkg.items())[0][0]) else: pkg2inst.append(f"{pkg}") log.debug("Installing these packages instead of %s: %s", name, pkg2inst) else: # install single package if version: pkg2inst = f"{name}@{version}" else: pkg2inst = f"{name}" cmd = ["pkg", "install", "-v", "--accept"] if test: cmd.append("-n") # Get a list of the packages before install so we can diff after to see # what got installed. old = list_pkgs() # Install or upgrade the package # If package is already installed if isinstance(pkg2inst, str): cmd.append(pkg2inst) elif isinstance(pkg2inst, list): cmd = cmd + pkg2inst out = __salt__["cmd.run_all"](cmd, output_loglevel="trace") # Get a list of the packages again, including newly installed ones. __context__.pop("pkg.list_pkgs", None) new = list_pkgs() ret = salt.utils.data.compare_dicts(old, new) if out["retcode"] != 0: raise CommandExecutionError( "Error occurred installing package(s)", info={ "changes": ret, "retcode": ips_pkg_return_values[out["retcode"]], "errors": [out["stderr"]], }, ) # No error occurred if test: return "Test succeeded." return ret def remove(name=None, pkgs=None, **kwargs): """ Remove specified package. Accepts full or partial FMRI. In case of multiple match, the command fails and won't modify the OS. name The name of the package to be deleted. Multiple Package Options: pkgs A list of packages to delete. Must be passed as a python list. The ``name`` parameter will be ignored if this option is passed. Returns a list containing the removed packages. CLI Example: .. code-block:: bash salt '*' pkg.remove <package name> salt '*' pkg.remove tcsh salt '*' pkg.remove pkg://solaris/shell/tcsh salt '*' pkg.remove pkgs='["foo", "bar"]' """ targets = salt.utils.args.split_input(pkgs) if pkgs else [name] if not targets: return {} if pkgs: log.debug("Removing these packages instead of %s: %s", name, targets) # Get a list of the currently installed pkgs. old = list_pkgs() # Remove the package(s) cmd = ["/bin/pkg", "uninstall", "-v"] + targets out = __salt__["cmd.run_all"](cmd, output_loglevel="trace") # Get a list of the packages after the uninstall __context__.pop("pkg.list_pkgs", None) new = list_pkgs() ret = salt.utils.data.compare_dicts(old, new) if out["retcode"] != 0: raise CommandExecutionError( "Error occurred removing package(s)", info={ "changes": ret, "retcode": ips_pkg_return_values[out["retcode"]], "errors": [out["stderr"]], }, ) return ret def purge(name, **kwargs): """ Remove specified package. Accepts full or partial FMRI. Returns a list containing the removed packages. CLI Example: .. code-block:: bash salt '*' pkg.purge <package name> """ return remove(name, **kwargs)