%PDF- %PDF-
Direktori : /lib/python2.7/site-packages/salt/modules/ |
Current File : //lib/python2.7/site-packages/salt/modules/win_wusa.py |
# -*- coding: utf-8 -*- ''' Microsoft Update files management via wusa.exe :maintainer: Thomas Lemarchand :platform: Windows :depends: PowerShell .. versionadded:: 2018.3.4 ''' # Import python libs from __future__ import absolute_import, unicode_literals import logging import os # Import salt libs import salt.utils.platform from salt.exceptions import CommandExecutionError log = logging.getLogger(__name__) # Define the module's virtual name __virtualname__ = 'wusa' def __virtual__(): ''' Load only on Windows ''' if not salt.utils.platform.is_windows(): return False, 'Only available on Windows systems' powershell_info = __salt__['cmd.shell_info'](shell='powershell', list_modules=False) if not powershell_info['installed']: return False, 'PowerShell not available' return __virtualname__ def _pshell_json(cmd, cwd=None): ''' Execute the desired powershell command and ensure that it returns data in JSON format and load that into python ''' if 'convertto-json' not in cmd.lower(): cmd = '{0} | ConvertTo-Json'.format(cmd) log.debug('PowerShell: %s', cmd) ret = __salt__['cmd.run_all'](cmd, shell='powershell', cwd=cwd) if 'pid' in ret: del ret['pid'] if ret.get('stderr', ''): error = ret['stderr'].splitlines()[0] raise CommandExecutionError(error, info=ret) if 'retcode' not in ret or ret['retcode'] != 0: # run_all logs an error to log.error, fail hard back to the user raise CommandExecutionError( 'Issue executing PowerShell {0}'.format(cmd), info=ret) # Sometimes Powershell returns an empty string, which isn't valid JSON if ret['stdout'] == '': ret['stdout'] = '{}' try: ret = salt.utils.json.loads(ret['stdout'], strict=False) except ValueError: raise CommandExecutionError( 'No JSON results from PowerShell', info=ret) return ret def is_installed(name): ''' Check if a specific KB is installed. Args: name (str): The name of the KB to check Returns: bool: ``True`` if installed, otherwise ``False`` CLI Example: .. code-block:: bash salt '*' wusa.is_installed KB123456 ''' return __salt__['cmd.retcode'](cmd='Get-HotFix -Id {0}'.format(name), shell='powershell', ignore_retcode=True) == 0 def install(path, restart=False): ''' Install a KB from a .msu file. Args: path (str): The full path to the msu file to install restart (bool): ``True`` to force a restart if required by the installation. Adds the ``/forcerestart`` switch to the ``wusa.exe`` command. ``False`` will add the ``/norestart`` switch instead. Default is ``False`` Returns: bool: ``True`` if successful, otherwise ``False`` Raise: CommandExecutionError: If the package is already installed or an error is encountered CLI Example: .. code-block:: bash salt '*' wusa.install C:/temp/KB123456.msu ''' # Build the command cmd = ['wusa.exe', path, '/quiet'] if restart: cmd.append('/forcerestart') else: cmd.append('/norestart') # Run the command ret_code = __salt__['cmd.retcode'](cmd, ignore_retcode=True) # Check the ret_code file_name = os.path.basename(path) errors = {2359302: '{0} is already installed'.format(file_name), 87: 'Unknown error'} if ret_code in errors: raise CommandExecutionError(errors[ret_code]) elif ret_code: raise CommandExecutionError('Unknown error: {0}'.format(ret_code)) return True def uninstall(path, restart=False): ''' Uninstall a specific KB. Args: path (str): The full path to the msu file to uninstall. This can also be just the name of the KB to uninstall restart (bool): ``True`` to force a restart if required by the installation. Adds the ``/forcerestart`` switch to the ``wusa.exe`` command. ``False`` will add the ``/norestart`` switch instead. Default is ``False`` Returns: bool: ``True`` if successful, otherwise ``False`` Raises: CommandExecutionError: If an error is encountered CLI Example: .. code-block:: bash salt '*' wusa.uninstall KB123456 # or salt '*' wusa.uninstall C:/temp/KB123456.msu ''' # Build the command cmd = ['wusa.exe', '/uninstall', '/quiet'] kb = os.path.splitext(os.path.basename(path))[0] if os.path.exists(path): cmd.append(path) else: cmd.append( '/kb:{0}'.format(kb[2:] if kb.lower().startswith('kb') else kb)) if restart: cmd.append('/forcerestart') else: cmd.append('/norestart') # Run the command ret_code = __salt__['cmd.retcode'](cmd, ignore_retcode=True) # Check the ret_code # If you pass /quiet and specify /kb, you'll always get retcode 87 if there # is an error. Use the actual file to get a more descriptive error errors = {-2145116156: '{0} does not support uninstall'.format(kb), 2359303: '{0} not installed'.format(kb), 87: 'Unknown error. Try specifying an .msu file'} if ret_code in errors: raise CommandExecutionError(errors[ret_code]) elif ret_code: raise CommandExecutionError('Unknown error: {0}'.format(ret_code)) return True def list(): ''' Get a list of updates installed on the machine Returns: list: A list of installed updates CLI Example: .. code-block:: bash salt '*' wusa.list ''' kbs = [] ret = _pshell_json('Get-HotFix | Select HotFixID') for item in ret: kbs.append(item['HotFixID']) return kbs