%PDF- %PDF-
Direktori : /lib/python2.7/site-packages/salt/modules/ |
Current File : //lib/python2.7/site-packages/salt/modules/solarispkg.py |
# -*- coding: utf-8 -*- ''' Package 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>`. ''' from __future__ import absolute_import, print_function, unicode_literals # Import python libs import copy import os import logging # Import salt libs import salt.utils.data import salt.utils.functools import salt.utils.files import salt.utils.stringutils from salt.exceptions import CommandExecutionError, MinionError log = logging.getLogger(__name__) # Define the module's virtual name __virtualname__ = 'pkg' def __virtual__(): ''' Set the virtual pkg module if the os is Solaris ''' if __grains__['os_family'] == 'Solaris' and float(__grains__['kernelrelease']) <= 5.10: return __virtualname__ return (False, 'The solarispkg execution module failed to load: only available ' 'on Solaris <= 10.') def _write_adminfile(kwargs): ''' Create a temporary adminfile based on the keyword arguments passed to pkg.install. ''' # Set the adminfile default variables email = kwargs.get('email', '') instance = kwargs.get('instance', 'quit') partial = kwargs.get('partial', 'nocheck') runlevel = kwargs.get('runlevel', 'nocheck') idepend = kwargs.get('idepend', 'nocheck') rdepend = kwargs.get('rdepend', 'nocheck') space = kwargs.get('space', 'nocheck') setuid = kwargs.get('setuid', 'nocheck') conflict = kwargs.get('conflict', 'nocheck') action = kwargs.get('action', 'nocheck') basedir = kwargs.get('basedir', 'default') # Make tempfile to hold the adminfile contents. adminfile = salt.utils.files.mkstemp(prefix="salt-") def _write_line(fp_, line): fp_.write(salt.utils.stringutils.to_str(line)) with salt.utils.files.fopen(adminfile, 'w') as fp_: _write_line(fp_, 'email={0}\n'.format(email)) _write_line(fp_, 'instance={0}\n'.format(instance)) _write_line(fp_, 'partial={0}\n'.format(partial)) _write_line(fp_, 'runlevel={0}\n'.format(runlevel)) _write_line(fp_, 'idepend={0}\n'.format(idepend)) _write_line(fp_, 'rdepend={0}\n'.format(rdepend)) _write_line(fp_, 'space={0}\n'.format(space)) _write_line(fp_, 'setuid={0}\n'.format(setuid)) _write_line(fp_, 'conflict={0}\n'.format(conflict)) _write_line(fp_, 'action={0}\n'.format(action)) _write_line(fp_, 'basedir={0}\n'.format(basedir)) return adminfile def list_pkgs(versions_as_list=False, **kwargs): ''' List the packages currently installed as a dict: .. code-block:: python {'<package_name>': '<version>'} CLI Example: .. code-block:: bash salt '*' pkg.list_pkgs ''' versions_as_list = salt.utils.data.is_true(versions_as_list) # 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__: if versions_as_list: return __context__['pkg.list_pkgs'] else: ret = copy.deepcopy(__context__['pkg.list_pkgs']) __salt__['pkg_resource.stringify'](ret) return ret ret = {} cmd = '/usr/bin/pkginfo -x' # Package information returned two lines per package. On even-offset # lines, the package name is in the first column. On odd-offset lines, the # package version is in the second column. lines = __salt__['cmd.run']( cmd, output_loglevel='trace', python_shell=False).splitlines() for index, line in enumerate(lines): if index % 2 == 0: name = line.split()[0].strip() if index % 2 == 1: version_num = line.split()[1].strip() __salt__['pkg_resource.add_pkg'](ret, name, version_num) __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 latest_version(*names, **kwargs): ''' Return the latest version of the named package available for upgrade or installation. If more than one package name is specified, a dict of name/version pairs is returned. If the latest version of a given package is already installed, an empty string will be returned for that package. CLI Example: .. code-block:: bash salt '*' pkg.latest_version <package name> salt '*' pkg.latest_version <package1> <package2> <package3> ... NOTE: As package repositories are not presently supported for Solaris pkgadd, this function will always return an empty string for a given package. ''' kwargs.pop('refresh', True) ret = {} if not names: return '' for name in names: ret[name] = '' # Return a string if only one package name passed if len(names) == 1: return ret[names[0]] return ret # available_version is being deprecated available_version = salt.utils.functools.alias_function(latest_version, 'available_version') def upgrade_available(name): ''' Check whether or not an upgrade is available for a given package CLI Example: .. code-block:: bash salt '*' pkg.upgrade_available <package name> ''' return latest_version(name) != '' def version(*names, **kwargs): ''' Returns a string representing the package version or an empty string if not installed. If more than one package name is specified, a dict of name/version pairs is returned. CLI Example: .. code-block:: bash salt '*' pkg.version <package name> salt '*' pkg.version <package1> <package2> <package3> ... ''' return __salt__['pkg_resource.version'](*names, **kwargs) def install(name=None, sources=None, saltenv='base', **kwargs): ''' Install the passed package. Can install packages from the following sources: * Locally (package already exists on the minion * HTTP/HTTPS server * FTP server * Salt master Returns a dict containing the new package names and versions: .. code-block:: python {'<package>': {'old': '<old-version>', 'new': '<new-version>'}} CLI Examples: .. code-block:: bash # Installing a data stream pkg that already exists on the minion salt '*' pkg.install sources='[{"<pkg name>": "/dir/on/minion/<pkg filename>"}]' salt '*' pkg.install sources='[{"SMClgcc346": "/var/spool/pkg/gcc-3.4.6-sol10-sparc-local.pkg"}]' # Installing a data stream pkg that exists on the salt master salt '*' pkg.install sources='[{"<pkg name>": "salt://pkgs/<pkg filename>"}]' salt '*' pkg.install sources='[{"SMClgcc346": "salt://pkgs/gcc-3.4.6-sol10-sparc-local.pkg"}]' CLI Example: .. code-block:: bash # Installing a data stream pkg that exists on a HTTP server salt '*' pkg.install sources='[{"<pkg name>": "http://packages.server.com/<pkg filename>"}]' salt '*' pkg.install sources='[{"SMClgcc346": "http://packages.server.com/gcc-3.4.6-sol10-sparc-local.pkg"}]' If working with solaris zones and you want to install a package only in the global zone you can pass 'current_zone_only=True' to salt to have the package only installed in the global zone. (Behind the scenes this is passing '-G' to the pkgadd command.) Solaris default when installing a package in the global zone is to install it in all zones. This overrides that and installs the package only in the global. CLI Example: .. code-block:: bash # Installing a data stream package only in the global zone: salt 'global_zone' pkg.install sources='[{"SMClgcc346": "/var/spool/pkg/gcc-3.4.6-sol10-sparc-local.pkg"}]' current_zone_only=True By default salt automatically provides an adminfile, to automate package installation, with these options set:: email= instance=quit partial=nocheck runlevel=nocheck idepend=nocheck rdepend=nocheck space=nocheck setuid=nocheck conflict=nocheck action=nocheck basedir=default You can override any of these options in two ways. First you can optionally pass any of the options as a kwarg to the module/state to override the default value or you can optionally pass the 'admin_source' option providing your own adminfile to the minions. Note: You can find all of the possible options to provide to the adminfile by reading the admin man page: .. code-block:: bash man -s 4 admin CLI Example: .. code-block:: bash # Overriding the 'instance' adminfile option when calling the module directly salt '*' pkg.install sources='[{"<pkg name>": "salt://pkgs/<pkg filename>"}]' instance="overwrite" SLS Example: .. code-block:: yaml # Overriding the 'instance' adminfile option when used in a state SMClgcc346: pkg.installed: - sources: - SMClgcc346: salt://srv/salt/pkgs/gcc-3.4.6-sol10-sparc-local.pkg - instance: overwrite .. note:: The ID declaration is ignored, as the package name is read from the ``sources`` parameter. CLI Example: .. code-block:: bash # Providing your own adminfile when calling the module directly salt '*' pkg.install sources='[{"<pkg name>": "salt://pkgs/<pkg filename>"}]' admin_source='salt://pkgs/<adminfile filename>' # Providing your own adminfile when using states <pkg name>: pkg.installed: - sources: - <pkg name>: salt://pkgs/<pkg filename> - admin_source: salt://pkgs/<adminfile filename> .. note:: The ID declaration is ignored, as the package name is read from the ``sources`` parameter. ''' if salt.utils.data.is_true(kwargs.get('refresh')): log.warning('\'refresh\' argument not implemented for solarispkg ' 'module') # pkgs is not supported, but must be passed here for API compatibility pkgs = kwargs.pop('pkgs', None) try: pkg_params, pkg_type = __salt__['pkg_resource.parse_targets']( name, pkgs, sources, **kwargs ) except MinionError as exc: raise CommandExecutionError(exc) if pkg_params is None or len(pkg_params) == 0: return {} if not sources: log.error('"sources" param required for solaris pkg_add installs') return {} try: if 'admin_source' in kwargs: adminfile = __salt__['cp.cache_file'](kwargs['admin_source'], saltenv) else: adminfile = _write_adminfile(kwargs) old = list_pkgs() cmd_prefix = ['/usr/sbin/pkgadd', '-n', '-a', adminfile] # Only makes sense in a global zone but works fine in non-globals. if kwargs.get('current_zone_only') == 'True': cmd_prefix += '-G ' errors = [] for pkg in pkg_params: cmd = cmd_prefix + ['-d', pkg, 'all'] # Install the package{s} out = __salt__['cmd.run_all'](cmd, output_loglevel='trace', python_shell=False) if out['retcode'] != 0 and out['stderr']: errors.append(out['stderr']) __context__.pop('pkg.list_pkgs', None) new = list_pkgs() ret = salt.utils.data.compare_dicts(old, new) if errors: raise CommandExecutionError( 'Problem encountered installing package(s)', info={'errors': errors, 'changes': ret} ) finally: # Remove the temp adminfile if 'admin_source' not in kwargs: try: os.remove(adminfile) except (NameError, OSError): pass return ret def remove(name=None, pkgs=None, saltenv='base', **kwargs): ''' Remove packages with pkgrm name The name of the package to be deleted By default salt automatically provides an adminfile, to automate package removal, with these options set:: email= instance=quit partial=nocheck runlevel=nocheck idepend=nocheck rdepend=nocheck space=nocheck setuid=nocheck conflict=nocheck action=nocheck basedir=default You can override any of these options in two ways. First you can optionally pass any of the options as a kwarg to the module/state to override the default value or you can optionally pass the 'admin_source' option providing your own adminfile to the minions. Note: You can find all of the possible options to provide to the adminfile by reading the admin man page: .. code-block:: bash man -s 4 admin 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. .. versionadded:: 0.16.0 Returns a dict containing the changes. CLI Example: .. code-block:: bash salt '*' pkg.remove <package name> salt '*' pkg.remove SUNWgit salt '*' pkg.remove <package1>,<package2>,<package3> salt '*' pkg.remove pkgs='["foo", "bar"]' ''' try: pkg_params = __salt__['pkg_resource.parse_targets'](name, pkgs)[0] except MinionError as exc: raise CommandExecutionError(exc) old = list_pkgs() targets = [x for x in pkg_params if x in old] if not targets: return {} try: if 'admin_source' in kwargs: adminfile = __salt__['cp.cache_file'](kwargs['admin_source'], saltenv) else: # Make tempfile to hold the adminfile contents. adminfile = _write_adminfile(kwargs) # Remove the package cmd = ['/usr/sbin/pkgrm', '-n', '-a', adminfile] + targets out = __salt__['cmd.run_all'](cmd, python_shell=False, output_loglevel='trace') if out['retcode'] != 0 and out['stderr']: errors = [out['stderr']] else: errors = [] __context__.pop('pkg.list_pkgs', None) new = list_pkgs() ret = salt.utils.data.compare_dicts(old, new) if errors: raise CommandExecutionError( 'Problem encountered removing package(s)', info={'errors': errors, 'changes': ret} ) finally: # Remove the temp adminfile if 'admin_source' not in kwargs: try: os.remove(adminfile) except (NameError, OSError): pass return ret def purge(name=None, pkgs=None, **kwargs): ''' Package purges are not supported, this function is identical to ``remove()``. 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. .. versionadded:: 0.16.0 Returns a dict containing the changes. CLI Example: .. code-block:: bash salt '*' pkg.purge <package name> salt '*' pkg.purge <package1>,<package2>,<package3> salt '*' pkg.purge pkgs='["foo", "bar"]' ''' return remove(name=name, pkgs=pkgs, **kwargs)