"Fossies" - the Fresh Open Source Software Archive

Member "salt-3002.2/salt/modules/win_wua.py" (18 Nov 2020, 38970 Bytes) of package /linux/misc/salt-3002.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "win_wua.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3002.1_vs_3002.2.

    1 """
    2 Module for managing Windows Updates using the Windows Update Agent.
    3 
    4 List updates on the system using the following functions:
    5 
    6 - :py:func:`win_wua.available <salt.modules.win_wua.available>`
    7 - :py:func:`win_wua.list <salt.modules.win_wua.list_>`
    8 
    9 This is an easy way to find additional information about updates available to
   10 to the system, such as the GUID, KB number, or description.
   11 
   12 Once you have the GUID or a KB number for the update you can get information
   13 about the update, download, install, or uninstall it using these functions:
   14 
   15 - :py:func:`win_wua.get <salt.modules.win_wua.get>`
   16 - :py:func:`win_wua.download <salt.modules.win_wua.download>`
   17 - :py:func:`win_wua.install <salt.modules.win_wua.install>`
   18 - :py:func:`win_wua.uninstall <salt.modules.win_wua.uninstall>`
   19 
   20 The get function expects a name in the form of a GUID, KB, or Title and should
   21 return information about a single update. The other functions accept either a
   22 single item or a list of items for downloading/installing/uninstalling a
   23 specific list of items.
   24 
   25 The :py:func:`win_wua.list <salt.modules.win_wua.list_>` and
   26 :py:func:`win_wua.get <salt.modules.win_wua.get>` functions are utility
   27 functions. In addition to returning information about updates they can also
   28 download and install updates by setting ``download=True`` or ``install=True``.
   29 So, with py:func:`win_wua.list <salt.modules.win_wua.list_>` for example, you
   30 could run the function with the filters you want to see what is available. Then
   31 just add ``install=True`` to install everything on that list.
   32 
   33 If you want to download, install, or uninstall specific updates, use
   34 :py:func:`win_wua.download <salt.modules.win_wua.download>`,
   35 :py:func:`win_wua.install <salt.modules.win_wua.install>`, or
   36 :py:func:`win_wua.uninstall <salt.modules.win_wua.uninstall>`. To update your
   37 system with the latest updates use :py:func:`win_wua.list
   38 <salt.modules.win_wua.list_>` and set ``install=True``
   39 
   40 You can also adjust the Windows Update settings using the
   41 :py:func:`win_wua.set_wu_settings <salt.modules.win_wua.set_wu_settings>`
   42 function. This function is only supported on the following operating systems:
   43 
   44 - Windows Vista / Server 2008
   45 - Windows 7 / Server 2008R2
   46 - Windows 8 / Server 2012
   47 - Windows 8.1 / Server 2012R2
   48 
   49 As of Windows 10 and Windows Server 2016, the ability to modify the Windows
   50 Update settings has been restricted. The settings can be modified in the Local
   51 Group Policy using the ``lgpo`` module.
   52 
   53 .. versionadded:: 2015.8.0
   54 
   55 :depends: salt.utils.win_update
   56 """
   57 import logging
   58 
   59 import salt.utils.platform
   60 import salt.utils.win_service
   61 import salt.utils.win_update
   62 import salt.utils.winapi
   63 from salt.exceptions import CommandExecutionError
   64 
   65 try:
   66     import win32com.client
   67 
   68     HAS_PYWIN32 = True
   69 except ImportError:
   70     HAS_PYWIN32 = False
   71 
   72 log = logging.getLogger(__name__)
   73 
   74 __func_alias__ = {
   75     "list_": "list",
   76 }
   77 
   78 
   79 def __virtual__():
   80     """
   81     Only works on Windows systems with PyWin32
   82     """
   83     if not salt.utils.platform.is_windows():
   84         return False, "WUA: Only available on Windows systems"
   85 
   86     if not HAS_PYWIN32:
   87         return False, "WUA: Requires PyWin32 libraries"
   88 
   89     if not salt.utils.win_update.HAS_PYWIN32:
   90         return False, "WUA: Missing Libraries required by salt.utils.win_update"
   91 
   92     if salt.utils.win_service.info("wuauserv")["StartType"] == "Disabled":
   93         return (
   94             False,
   95             "WUA: The Windows Update service (wuauserv) must not be disabled",
   96         )
   97 
   98     if salt.utils.win_service.info("msiserver")["StartType"] == "Disabled":
   99         return (
  100             False,
  101             "WUA: The Windows Installer service (msiserver) must not be disabled",
  102         )
  103 
  104     if salt.utils.win_service.info("BITS")["StartType"] == "Disabled":
  105         return (
  106             False,
  107             "WUA: The Background Intelligent Transfer service (bits) must not "
  108             "be disabled",
  109         )
  110 
  111     if not salt.utils.win_service.info("CryptSvc")["StartType"] == "Auto":
  112         return (
  113             False,
  114             "WUA: The Cryptographic Services service (CryptSvc) must not be "
  115             "disabled",
  116         )
  117 
  118     if salt.utils.win_service.info("TrustedInstaller")["StartType"] == "Disabled":
  119         return (
  120             False,
  121             "WUA: The Windows Module Installer service (TrustedInstaller) must "
  122             "not be disabled",
  123         )
  124 
  125     return True
  126 
  127 
  128 def available(
  129     software=True,
  130     drivers=True,
  131     summary=False,
  132     skip_installed=True,
  133     skip_hidden=True,
  134     skip_mandatory=False,
  135     skip_reboot=False,
  136     categories=None,
  137     severities=None,
  138     online=True,
  139 ):
  140     """
  141     .. versionadded:: 2017.7.0
  142 
  143     List updates that match the passed criteria. This allows for more filter
  144     options than :func:`list`. Good for finding a specific GUID or KB.
  145 
  146     Args:
  147 
  148         software (bool):
  149             Include software updates in the results. Default is ``True``
  150 
  151         drivers (bool):
  152             Include driver updates in the results. Default is ``True``
  153 
  154         summary (bool):
  155             - ``True``: Return a summary of updates available for each category.
  156             - ``False`` (default): Return a detailed list of available updates.
  157 
  158         skip_installed (bool):
  159             Skip updates that are already installed. Default is ``True``
  160 
  161         skip_hidden (bool):
  162             Skip updates that have been hidden. Default is ``True``
  163 
  164         skip_mandatory (bool):
  165             Skip mandatory updates. Default is ``False``
  166 
  167         skip_reboot (bool):
  168             Skip updates that require a reboot. Default is ``False``
  169 
  170         categories (list):
  171             Specify the categories to list. Must be passed as a list. All
  172             categories returned by default.
  173 
  174             Categories include the following:
  175 
  176             * Critical Updates
  177             * Definition Updates
  178             * Drivers (make sure you set ``drivers=True``)
  179             * Feature Packs
  180             * Security Updates
  181             * Update Rollups
  182             * Updates
  183             * Update Rollups
  184             * Windows 7
  185             * Windows 8.1
  186             * Windows 8.1 drivers
  187             * Windows 8.1 and later drivers
  188             * Windows Defender
  189 
  190         severities (list):
  191             Specify the severities to include. Must be passed as a list. All
  192             severities returned by default.
  193 
  194             Severities include the following:
  195 
  196             * Critical
  197             * Important
  198 
  199         online (bool):
  200             Tells the Windows Update Agent go online to update its local update
  201             database. ``True`` will go online. ``False`` will use the local
  202             update database as is. Default is ``True``
  203 
  204             .. versionadded:: 3001
  205 
  206     Returns:
  207 
  208         dict: Returns a dict containing either a summary or a list of updates:
  209 
  210         .. code-block:: cfg
  211 
  212             Dict of Updates:
  213             {'<GUID>': {
  214                 'Title': <title>,
  215                 'KB': <KB>,
  216                 'GUID': <the globally unique identifier for the update>,
  217                 'Description': <description>,
  218                 'Downloaded': <has the update been downloaded>,
  219                 'Installed': <has the update been installed>,
  220                 'Mandatory': <is the update mandatory>,
  221                 'UserInput': <is user input required>,
  222                 'EULAAccepted': <has the EULA been accepted>,
  223                 'Severity': <update severity>,
  224                 'NeedsReboot': <is the update installed and awaiting reboot>,
  225                 'RebootBehavior': <will the update require a reboot>,
  226                 'Categories': [
  227                     '<category 1>',
  228                     '<category 2>',
  229                     ... ]
  230             }}
  231 
  232             Summary of Updates:
  233             {'Total': <total number of updates returned>,
  234              'Available': <updates that are not downloaded or installed>,
  235              'Downloaded': <updates that are downloaded but not installed>,
  236              'Installed': <updates installed (usually 0 unless installed=True)>,
  237              'Categories': {
  238                 <category 1>: <total for that category>,
  239                 <category 2>: <total for category 2>,
  240                 ... }
  241             }
  242 
  243     CLI Examples:
  244 
  245     .. code-block:: bash
  246 
  247         # Normal Usage (list all software updates)
  248         salt '*' win_wua.available
  249 
  250         # List all updates with categories of Critical Updates and Drivers
  251         salt '*' win_wua.available categories=["Critical Updates","Drivers"]
  252 
  253         # List all Critical Security Updates
  254         salt '*' win_wua.available categories=["Security Updates"] severities=["Critical"]
  255 
  256         # List all updates with a severity of Critical
  257         salt '*' win_wua.available severities=["Critical"]
  258 
  259         # A summary of all available updates
  260         salt '*' win_wua.available summary=True
  261 
  262         # A summary of all Feature Packs and Windows 8.1 Updates
  263         salt '*' win_wua.available categories=["Feature Packs","Windows 8.1"] summary=True
  264     """
  265 
  266     # Create a Windows Update Agent instance
  267     wua = salt.utils.win_update.WindowsUpdateAgent(online=online)
  268 
  269     # Look for available
  270     updates = wua.available(
  271         skip_hidden=skip_hidden,
  272         skip_installed=skip_installed,
  273         skip_mandatory=skip_mandatory,
  274         skip_reboot=skip_reboot,
  275         software=software,
  276         drivers=drivers,
  277         categories=categories,
  278         severities=severities,
  279     )
  280 
  281     # Return results as Summary or Details
  282     return updates.summary() if summary else updates.list()
  283 
  284 
  285 def get(name, download=False, install=False, online=True):
  286     """
  287     .. versionadded:: 2017.7.0
  288 
  289     Returns details for the named update
  290 
  291     Args:
  292 
  293         name (str):
  294             The name of the update you're searching for. This can be the GUID, a
  295             KB number, or any part of the name of the update. GUIDs and KBs are
  296             preferred. Run ``list`` to get the GUID for the update you're
  297             looking for.
  298 
  299         download (bool):
  300             Download the update returned by this function. Run this function
  301             first to see if the update exists, then set ``download=True`` to
  302             download the update.
  303 
  304         install (bool):
  305             Install the update returned by this function. Run this function
  306             first to see if the update exists, then set ``install=True`` to
  307             install the update.
  308 
  309         online (bool):
  310             Tells the Windows Update Agent go online to update its local update
  311             database. ``True`` will go online. ``False`` will use the local
  312             update database as is. Default is ``True``
  313 
  314             .. versionadded:: 3001
  315 
  316     Returns:
  317 
  318         dict:
  319             Returns a dict containing a list of updates that match the name if
  320             download and install are both set to False. Should usually be a
  321             single update, but can return multiple if a partial name is given.
  322 
  323         If download or install is set to true it will return the results of the
  324         operation.
  325 
  326         .. code-block:: cfg
  327 
  328             Dict of Updates:
  329             {'<GUID>': {
  330                 'Title': <title>,
  331                 'KB': <KB>,
  332                 'GUID': <the globally unique identifier for the update>,
  333                 'Description': <description>,
  334                 'Downloaded': <has the update been downloaded>,
  335                 'Installed': <has the update been installed>,
  336                 'Mandatory': <is the update mandatory>,
  337                 'UserInput': <is user input required>,
  338                 'EULAAccepted': <has the EULA been accepted>,
  339                 'Severity': <update severity>,
  340                 'NeedsReboot': <is the update installed and awaiting reboot>,
  341                 'RebootBehavior': <will the update require a reboot>,
  342                 'Categories': [
  343                     '<category 1>',
  344                     '<category 2>',
  345                     ... ]
  346             }}
  347 
  348     CLI Examples:
  349 
  350     .. code-block:: bash
  351 
  352         # Recommended Usage using GUID without braces
  353         # Use this to find the status of a specific update
  354         salt '*' win_wua.get 12345678-abcd-1234-abcd-1234567890ab
  355 
  356         # Use the following if you don't know the GUID:
  357 
  358         # Using a KB number
  359         # Not all updates have an associated KB
  360         salt '*' win_wua.get KB3030298
  361 
  362         # Using part or all of the name of the update
  363         # Could possibly return multiple results
  364         # Not all updates have an associated KB
  365         salt '*' win_wua.get 'Microsoft Camera Codec Pack'
  366     """
  367     # Create a Windows Update Agent instance
  368     wua = salt.utils.win_update.WindowsUpdateAgent(online=online)
  369 
  370     # Search for Update
  371     updates = wua.search(name)
  372 
  373     ret = {}
  374 
  375     # Download
  376     if download or install:
  377         ret["Download"] = wua.download(updates)
  378 
  379     # Install
  380     if install:
  381         ret["Install"] = wua.install(updates)
  382 
  383     return ret if ret else updates.list()
  384 
  385 
  386 def list(
  387     software=True,
  388     drivers=False,
  389     summary=False,
  390     skip_installed=True,
  391     categories=None,
  392     severities=None,
  393     download=False,
  394     install=False,
  395     online=True,
  396 ):
  397     """
  398     .. versionadded:: 2017.7.0
  399 
  400     Returns a detailed list of available updates or a summary. If ``download``
  401     or ``install`` is ``True`` the same list will be downloaded and/or
  402     installed.
  403 
  404     Args:
  405 
  406         software (bool):
  407             Include software updates in the results. Default is ``True``
  408 
  409         drivers (bool):
  410             Include driver updates in the results. Default is ``False``
  411 
  412         summary (bool):
  413             - ``True``: Return a summary of updates available for each category.
  414             - ``False`` (default): Return a detailed list of available updates.
  415 
  416         skip_installed (bool):
  417             Skip installed updates in the results. Default is ``True``
  418 
  419         download (bool):
  420             (Overrides reporting functionality) Download the list of updates
  421             returned by this function. Run this function first with
  422             ``download=False`` to see what will be downloaded, then set
  423             ``download=True`` to download the updates. Default is ``False``
  424 
  425         install (bool):
  426             (Overrides reporting functionality) Install the list of updates
  427             returned by this function. Run this function first with
  428             ``install=False`` to see what will be installed, then set
  429             ``install=True`` to install the updates. Default is ``False``
  430 
  431         categories (list):
  432             Specify the categories to list. Must be passed as a list. All
  433             categories returned by default.
  434 
  435             Categories include the following:
  436 
  437             * Critical Updates
  438             * Definition Updates
  439             * Drivers (make sure you set ``drivers=True``)
  440             * Feature Packs
  441             * Security Updates
  442             * Update Rollups
  443             * Updates
  444             * Update Rollups
  445             * Windows 7
  446             * Windows 8.1
  447             * Windows 8.1 drivers
  448             * Windows 8.1 and later drivers
  449             * Windows Defender
  450 
  451         severities (list):
  452             Specify the severities to include. Must be passed as a list. All
  453             severities returned by default.
  454 
  455             Severities include the following:
  456 
  457             * Critical
  458             * Important
  459 
  460         online (bool):
  461             Tells the Windows Update Agent go online to update its local update
  462             database. ``True`` will go online. ``False`` will use the local
  463             update database as is. Default is ``True``
  464 
  465             .. versionadded:: 3001
  466 
  467     Returns:
  468 
  469         dict: Returns a dict containing either a summary or a list of updates:
  470 
  471         .. code-block:: cfg
  472 
  473             Dict of Updates:
  474             {'<GUID>': {
  475                 'Title': <title>,
  476                 'KB': <KB>,
  477                 'GUID': <the globally unique identifier for the update>,
  478                 'Description': <description>,
  479                 'Downloaded': <has the update been downloaded>,
  480                 'Installed': <has the update been installed>,
  481                 'Mandatory': <is the update mandatory>,
  482                 'UserInput': <is user input required>,
  483                 'EULAAccepted': <has the EULA been accepted>,
  484                 'Severity': <update severity>,
  485                 'NeedsReboot': <is the update installed and awaiting reboot>,
  486                 'RebootBehavior': <will the update require a reboot>,
  487                 'Categories': [
  488                     '<category 1>',
  489                     '<category 2>',
  490                     ... ]
  491             }}
  492 
  493             Summary of Updates:
  494             {'Total': <total number of updates returned>,
  495              'Available': <updates that are not downloaded or installed>,
  496              'Downloaded': <updates that are downloaded but not installed>,
  497              'Installed': <updates installed (usually 0 unless installed=True)>,
  498              'Categories': {
  499                 <category 1>: <total for that category>,
  500                 <category 2>: <total for category 2>,
  501                 ... }
  502             }
  503 
  504     CLI Examples:
  505 
  506     .. code-block:: bash
  507 
  508         # Normal Usage (list all software updates)
  509         salt '*' win_wua.list
  510 
  511         # List all updates with categories of Critical Updates and Drivers
  512         salt '*' win_wua.list categories=['Critical Updates','Drivers']
  513 
  514         # List all Critical Security Updates
  515         salt '*' win_wua.list categories=['Security Updates'] severities=['Critical']
  516 
  517         # List all updates with a severity of Critical
  518         salt '*' win_wua.list severities=['Critical']
  519 
  520         # A summary of all available updates
  521         salt '*' win_wua.list summary=True
  522 
  523         # A summary of all Feature Packs and Windows 8.1 Updates
  524         salt '*' win_wua.list categories=['Feature Packs','Windows 8.1'] summary=True
  525     """
  526     # Create a Windows Update Agent instance
  527     wua = salt.utils.win_update.WindowsUpdateAgent(online=online)
  528 
  529     # Search for Update
  530     updates = wua.available(
  531         skip_installed=skip_installed,
  532         software=software,
  533         drivers=drivers,
  534         categories=categories,
  535         severities=severities,
  536     )
  537 
  538     ret = {}
  539 
  540     # Download
  541     if download or install:
  542         ret["Download"] = wua.download(updates)
  543 
  544     # Install
  545     if install:
  546         ret["Install"] = wua.install(updates)
  547 
  548     if not ret:
  549         return updates.summary() if summary else updates.list()
  550 
  551     return ret
  552 
  553 
  554 def installed(summary=False, kbs_only=False):
  555     """
  556     .. versionadded:: 3001
  557 
  558     Get a list of all updates that are currently installed on the system.
  559 
  560     .. note::
  561 
  562         This list may not necessarily match the Update History on the machine.
  563         This will only show the updates that apply to the current build of
  564         Windows. So, for example, the system may have shipped with Windows 10
  565         Build 1607. That machine received updates to the 1607 build. Later the
  566         machine was upgraded to a newer feature release, 1803 for example. Then
  567         more updates were applied. This will only return the updates applied to
  568         the 1803 build and not those applied when the system was at the 1607
  569         build.
  570 
  571     Args:
  572 
  573         summary (bool):
  574             Return a summary instead of a detailed list of updates. ``True``
  575             will return a Summary, ``False`` will return a detailed list of
  576             installed updates. Default is ``False``
  577 
  578         kbs_only (bool):
  579             Only return a list of KBs installed on the system. If this parameter
  580             is passed, the ``summary`` parameter will be ignored. Default is
  581             ``False``
  582 
  583     Returns:
  584         dict:
  585             Returns a dictionary of either a Summary or a detailed list of
  586             updates installed on the system when ``kbs_only=False``
  587 
  588         list:
  589             Returns a list of KBs installed on the system when ``kbs_only=True``
  590 
  591     CLI Examples:
  592 
  593     .. code-block:: bash
  594 
  595         # Get a detailed list of all applicable updates installed on the system
  596         salt '*' win_wua.installed
  597 
  598         # Get a summary of all applicable updates installed on the system
  599         salt '*' win_wua.installed summary=True
  600 
  601         # Get a simple list of KBs installed on the system
  602         salt '*' win_wua.installed kbs_only=True
  603     """
  604     # Create a Windows Update Agent instance. Since we're only listing installed
  605     # updates, there's no need to go online to update the Windows Update db
  606     wua = salt.utils.win_update.WindowsUpdateAgent(online=False)
  607     updates = wua.installed()  # Get installed Updates objects
  608     results = updates.list()  # Convert to list
  609 
  610     if kbs_only:
  611         list_kbs = set()
  612         for item in results:
  613             list_kbs.update(results[item]["KBs"])
  614         return sorted(list_kbs)
  615 
  616     return updates.summary() if summary else results
  617 
  618 
  619 def download(names):
  620     """
  621     .. versionadded:: 2017.7.0
  622 
  623     Downloads updates that match the list of passed identifiers. It's easier to
  624     use this function by using list_updates and setting ``download=True``.
  625 
  626     Args:
  627 
  628         names (str, list):
  629             A single update or a list of updates to download. This can be any
  630             combination of GUIDs, KB numbers, or names. GUIDs or KBs are
  631             preferred.
  632 
  633             .. note::
  634 
  635                 An error will be raised if there are more results than there are
  636                 items in the names parameter
  637 
  638     Returns:
  639 
  640         dict: A dictionary containing the details about the downloaded updates
  641 
  642     CLI Example:
  643 
  644     .. code-block:: bash
  645 
  646         # Normal Usage
  647         salt '*' win_wua.download names=['12345678-abcd-1234-abcd-1234567890ab', 'KB2131233']
  648     """
  649     # Create a Windows Update Agent instance
  650     wua = salt.utils.win_update.WindowsUpdateAgent()
  651 
  652     # Search for Update
  653     updates = wua.search(names)
  654 
  655     if updates.count() == 0:
  656         raise CommandExecutionError("No updates found")
  657 
  658     # Make sure it's a list so count comparison is correct
  659     if isinstance(names, str):
  660         names = [names]
  661 
  662     if isinstance(names, int):
  663         names = [str(names)]
  664 
  665     if updates.count() > len(names):
  666         raise CommandExecutionError(
  667             "Multiple updates found, names need to be more specific"
  668         )
  669 
  670     return wua.download(updates)
  671 
  672 
  673 def install(names):
  674     """
  675     .. versionadded:: 2017.7.0
  676 
  677     Installs updates that match the list of identifiers. It may be easier to use
  678     the list_updates function and set ``install=True``.
  679 
  680     Args:
  681 
  682         names (str, list):
  683             A single update or a list of updates to install. This can be any
  684             combination of GUIDs, KB numbers, or names. GUIDs or KBs are
  685             preferred.
  686 
  687     .. note::
  688 
  689         An error will be raised if there are more results than there are items
  690         in the names parameter
  691 
  692     Returns:
  693 
  694         dict: A dictionary containing the details about the installed updates
  695 
  696     CLI Examples:
  697 
  698     .. code-block:: bash
  699 
  700         # Normal Usage
  701         salt '*' win_wua.install KB12323211
  702     """
  703     # Create a Windows Update Agent instance
  704     wua = salt.utils.win_update.WindowsUpdateAgent()
  705 
  706     # Search for Updates
  707     updates = wua.search(names)
  708 
  709     if updates.count() == 0:
  710         raise CommandExecutionError("No updates found")
  711 
  712     # Make sure it's a list so count comparison is correct
  713     if isinstance(names, str):
  714         names = [names]
  715 
  716     if isinstance(names, int):
  717         names = [str(names)]
  718 
  719     if updates.count() > len(names):
  720         raise CommandExecutionError(
  721             "Multiple updates found, names need to be more specific"
  722         )
  723 
  724     return wua.install(updates)
  725 
  726 
  727 def uninstall(names):
  728     """
  729     .. versionadded:: 2017.7.0
  730 
  731     Uninstall updates.
  732 
  733     Args:
  734 
  735         names (str, list):
  736             A single update or a list of updates to uninstall. This can be any
  737             combination of GUIDs, KB numbers, or names. GUIDs or KBs are
  738             preferred.
  739 
  740     Returns:
  741 
  742         dict: A dictionary containing the details about the uninstalled updates
  743 
  744     CLI Examples:
  745 
  746     .. code-block:: bash
  747 
  748         # Normal Usage
  749         salt '*' win_wua.uninstall KB3121212
  750 
  751         # As a list
  752         salt '*' win_wua.uninstall guid=['12345678-abcd-1234-abcd-1234567890ab', 'KB1231231']
  753     """
  754     # Create a Windows Update Agent instance
  755     wua = salt.utils.win_update.WindowsUpdateAgent()
  756 
  757     # Search for Updates
  758     updates = wua.search(names)
  759 
  760     if updates.count() == 0:
  761         raise CommandExecutionError("No updates found")
  762 
  763     return wua.uninstall(updates)
  764 
  765 
  766 def set_wu_settings(
  767     level=None,
  768     recommended=None,
  769     featured=None,
  770     elevated=None,
  771     msupdate=None,
  772     day=None,
  773     time=None,
  774 ):
  775     """
  776     Change Windows Update settings. If no parameters are passed, the current
  777     value will be returned.
  778 
  779     Supported:
  780         - Windows Vista / Server 2008
  781         - Windows 7 / Server 2008R2
  782         - Windows 8 / Server 2012
  783         - Windows 8.1 / Server 2012R2
  784 
  785     .. note:
  786         Microsoft began using the Unified Update Platform (UUP) starting with
  787         Windows 10 / Server 2016. The Windows Update settings have changed and
  788         the ability to 'Save' Windows Update settings has been removed. Windows
  789         Update settings are read-only. See MSDN documentation:
  790         https://msdn.microsoft.com/en-us/library/aa385829(v=vs.85).aspx
  791 
  792     Args:
  793 
  794         level (int):
  795             Number from 1 to 4 indicating the update level:
  796 
  797             1. Never check for updates
  798             2. Check for updates but let me choose whether to download and
  799                install them
  800             3. Download updates but let me choose whether to install them
  801             4. Install updates automatically
  802 
  803         recommended (bool):
  804             Boolean value that indicates whether to include optional or
  805             recommended updates when a search for updates and installation of
  806             updates is performed.
  807 
  808         featured (bool):
  809             Boolean value that indicates whether to display notifications for
  810             featured updates.
  811 
  812         elevated (bool):
  813             Boolean value that indicates whether non-administrators can perform
  814             some update-related actions without administrator approval.
  815 
  816         msupdate (bool):
  817             Boolean value that indicates whether to turn on Microsoft Update for
  818             other Microsoft products
  819 
  820         day (str):
  821             Days of the week on which Automatic Updates installs or uninstalls
  822             updates. Accepted values:
  823 
  824             - Everyday
  825             - Monday
  826             - Tuesday
  827             - Wednesday
  828             - Thursday
  829             - Friday
  830             - Saturday
  831 
  832         time (str):
  833             Time at which Automatic Updates installs or uninstalls updates. Must
  834             be in the ##:## 24hr format, eg. 3:00 PM would be 15:00. Must be in
  835             1 hour increments.
  836 
  837     Returns:
  838 
  839         dict: Returns a dictionary containing the results.
  840 
  841     CLI Examples:
  842 
  843     .. code-block:: bash
  844 
  845         salt '*' win_wua.set_wu_settings level=4 recommended=True featured=False
  846     """
  847     # The AutomaticUpdateSettings.Save() method used in this function does not
  848     # work on Windows 10 / Server 2016. It is called in throughout this function
  849     # like this:
  850     #
  851     # with salt.utils.winapi.Com():
  852     #     obj_au = win32com.client.Dispatch('Microsoft.Update.AutoUpdate')
  853     #     obj_au_settings = obj_au.Settings
  854     #     obj_au_settings.Save()
  855     #
  856     # The `Save()` method reports success but doesn't actually change anything.
  857     # Windows Update settings are read-only in Windows 10 / Server 2016. There's
  858     # a little blurb on MSDN that mentions this, but gives no alternative for
  859     # changing these settings in Windows 10 / Server 2016.
  860     #
  861     # https://msdn.microsoft.com/en-us/library/aa385829(v=vs.85).aspx
  862     #
  863     # Apparently the Windows Update framework in Windows Vista - Windows 8.1 has
  864     # been changed quite a bit in Windows 10 / Server 2016. It is now called the
  865     # Unified Update Platform (UUP). I haven't found an API or a Powershell
  866     # commandlet for working with the UUP. Perhaps there will be something
  867     # forthcoming. The `win_lgpo` module might be an option for changing the
  868     # Windows Update settings using local group policy.
  869     ret = {"Success": True}
  870 
  871     # Initialize the PyCom system
  872     with salt.utils.winapi.Com():
  873 
  874         # Create an AutoUpdate object
  875         obj_au = win32com.client.Dispatch("Microsoft.Update.AutoUpdate")
  876 
  877         # Create an AutoUpdate Settings Object
  878         obj_au_settings = obj_au.Settings
  879 
  880     # Only change the setting if it's passed
  881     if level is not None:
  882         obj_au_settings.NotificationLevel = int(level)
  883         result = obj_au_settings.Save()
  884         if result is None:
  885             ret["Level"] = level
  886         else:
  887             ret["Comment"] = "Settings failed to save. Check permissions."
  888             ret["Success"] = False
  889 
  890     if recommended is not None:
  891         obj_au_settings.IncludeRecommendedUpdates = recommended
  892         result = obj_au_settings.Save()
  893         if result is None:
  894             ret["Recommended"] = recommended
  895         else:
  896             ret["Comment"] = "Settings failed to save. Check permissions."
  897             ret["Success"] = False
  898 
  899     if featured is not None:
  900         obj_au_settings.FeaturedUpdatesEnabled = featured
  901         result = obj_au_settings.Save()
  902         if result is None:
  903             ret["Featured"] = featured
  904         else:
  905             ret["Comment"] = "Settings failed to save. Check permissions."
  906             ret["Success"] = False
  907 
  908     if elevated is not None:
  909         obj_au_settings.NonAdministratorsElevated = elevated
  910         result = obj_au_settings.Save()
  911         if result is None:
  912             ret["Elevated"] = elevated
  913         else:
  914             ret["Comment"] = "Settings failed to save. Check permissions."
  915             ret["Success"] = False
  916 
  917     if day is not None:
  918         # Check that day is valid
  919         days = {
  920             "Everyday": 0,
  921             "Sunday": 1,
  922             "Monday": 2,
  923             "Tuesday": 3,
  924             "Wednesday": 4,
  925             "Thursday": 5,
  926             "Friday": 6,
  927             "Saturday": 7,
  928         }
  929         if day not in days:
  930             ret["Comment"] = (
  931                 "Day needs to be one of the following: Everyday, "
  932                 "Monday, Tuesday, Wednesday, Thursday, Friday, "
  933                 "Saturday"
  934             )
  935             ret["Success"] = False
  936         else:
  937             # Set the numeric equivalent for the day setting
  938             obj_au_settings.ScheduledInstallationDay = days[day]
  939             result = obj_au_settings.Save()
  940             if result is None:
  941                 ret["Day"] = day
  942             else:
  943                 ret["Comment"] = "Settings failed to save. Check permissions."
  944                 ret["Success"] = False
  945 
  946     if time is not None:
  947         # Check for time as a string: if the time is not quoted, yaml will
  948         # treat it as an integer
  949         if not isinstance(time, str):
  950             ret["Comment"] = (
  951                 "Time argument needs to be a string; it may need to "
  952                 "be quoted. Passed {}. Time not set.".format(time)
  953             )
  954             ret["Success"] = False
  955         # Check for colon in the time
  956         elif ":" not in time:
  957             ret["Comment"] = (
  958                 "Time argument needs to be in 00:00 format. "
  959                 "Passed {}. Time not set.".format(time)
  960             )
  961             ret["Success"] = False
  962         else:
  963             # Split the time by :
  964             t = time.split(":")
  965             # We only need the hours value
  966             obj_au_settings.FeaturedUpdatesEnabled = t[0]
  967             result = obj_au_settings.Save()
  968             if result is None:
  969                 ret["Time"] = time
  970             else:
  971                 ret["Comment"] = "Settings failed to save. Check permissions."
  972                 ret["Success"] = False
  973 
  974     if msupdate is not None:
  975         # Microsoft Update requires special handling
  976         # First load the MS Update Service Manager
  977         with salt.utils.winapi.Com():
  978             obj_sm = win32com.client.Dispatch("Microsoft.Update.ServiceManager")
  979 
  980             # Give it a bogus name
  981             obj_sm.ClientApplicationID = "My App"
  982 
  983             if msupdate:
  984                 # msupdate is true, so add it to the services
  985                 try:
  986                     obj_sm.AddService2("7971f918-a847-4430-9279-4a52d1efe18d", 7, "")
  987                     ret["msupdate"] = msupdate
  988                 except Exception as error:  # pylint: disable=broad-except
  989                     # pylint: disable=unpacking-non-sequence,unbalanced-tuple-unpacking
  990                     (hr, msg, exc, arg,) = error.args
  991                     # pylint: enable=unpacking-non-sequence,unbalanced-tuple-unpacking
  992                     # Consider checking for -2147024891 (0x80070005) Access Denied
  993                     ret["Comment"] = "Failed with failure code: {}".format(exc[5])
  994                     ret["Success"] = False
  995             else:
  996                 # msupdate is false, so remove it from the services
  997                 # check to see if the update is there or the RemoveService function
  998                 # will fail
  999                 if _get_msupdate_status():
 1000                     # Service found, remove the service
 1001                     try:
 1002                         obj_sm.RemoveService("7971f918-a847-4430-9279-4a52d1efe18d")
 1003                         ret["msupdate"] = msupdate
 1004                     except Exception as error:  # pylint: disable=broad-except
 1005                         # pylint: disable=unpacking-non-sequence,unbalanced-tuple-unpacking
 1006                         (hr, msg, exc, arg,) = error.args
 1007                         # pylint: enable=unpacking-non-sequence,unbalanced-tuple-unpacking
 1008                         # Consider checking for the following
 1009                         # -2147024891 (0x80070005) Access Denied
 1010                         # -2145091564 (0x80248014) Service Not Found (shouldn't get
 1011                         # this with the check for _get_msupdate_status above
 1012                         ret["Comment"] = "Failed with failure code: {}".format(exc[5])
 1013                         ret["Success"] = False
 1014                 else:
 1015                     ret["msupdate"] = msupdate
 1016 
 1017     ret["Reboot"] = get_needs_reboot()
 1018 
 1019     return ret
 1020 
 1021 
 1022 def get_wu_settings():
 1023     """
 1024     Get current Windows Update settings.
 1025 
 1026     Returns:
 1027 
 1028         dict: A dictionary of Windows Update settings:
 1029 
 1030         Featured Updates:
 1031             Boolean value that indicates whether to display notifications for
 1032             featured updates.
 1033 
 1034         Group Policy Required (Read-only):
 1035             Boolean value that indicates whether Group Policy requires the
 1036             Automatic Updates service.
 1037 
 1038         Microsoft Update:
 1039             Boolean value that indicates whether to turn on Microsoft Update for
 1040             other Microsoft Products
 1041 
 1042         Needs Reboot:
 1043             Boolean value that indicates whether the machine is in a reboot
 1044             pending state.
 1045 
 1046         Non Admins Elevated:
 1047             Boolean value that indicates whether non-administrators can perform
 1048             some update-related actions without administrator approval.
 1049 
 1050         Notification Level:
 1051 
 1052             Number 1 to 4 indicating the update level:
 1053 
 1054                 1. Never check for updates
 1055                 2. Check for updates but let me choose whether to download and
 1056                    install them
 1057                 3. Download updates but let me choose whether to install them
 1058                 4. Install updates automatically
 1059 
 1060         Read Only (Read-only):
 1061             Boolean value that indicates whether the Automatic Update
 1062             settings are read-only.
 1063 
 1064         Recommended Updates:
 1065             Boolean value that indicates whether to include optional or
 1066             recommended updates when a search for updates and installation of
 1067             updates is performed.
 1068 
 1069         Scheduled Day:
 1070             Days of the week on which Automatic Updates installs or uninstalls
 1071             updates.
 1072 
 1073         Scheduled Time:
 1074             Time at which Automatic Updates installs or uninstalls updates.
 1075 
 1076     CLI Examples:
 1077 
 1078     .. code-block:: bash
 1079 
 1080         salt '*' win_wua.get_wu_settings
 1081     """
 1082     ret = {}
 1083 
 1084     day = [
 1085         "Every Day",
 1086         "Sunday",
 1087         "Monday",
 1088         "Tuesday",
 1089         "Wednesday",
 1090         "Thursday",
 1091         "Friday",
 1092         "Saturday",
 1093     ]
 1094 
 1095     # Initialize the PyCom system
 1096     with salt.utils.winapi.Com():
 1097         # Create an AutoUpdate object
 1098         obj_au = win32com.client.Dispatch("Microsoft.Update.AutoUpdate")
 1099 
 1100         # Create an AutoUpdate Settings Object
 1101         obj_au_settings = obj_au.Settings
 1102 
 1103         # Populate the return dictionary
 1104         ret["Featured Updates"] = obj_au_settings.FeaturedUpdatesEnabled
 1105         ret["Group Policy Required"] = obj_au_settings.Required
 1106         ret["Microsoft Update"] = _get_msupdate_status()
 1107         ret["Needs Reboot"] = get_needs_reboot()
 1108         ret["Non Admins Elevated"] = obj_au_settings.NonAdministratorsElevated
 1109         ret["Notification Level"] = obj_au_settings.NotificationLevel
 1110         ret["Read Only"] = obj_au_settings.ReadOnly
 1111         ret["Recommended Updates"] = obj_au_settings.IncludeRecommendedUpdates
 1112         ret["Scheduled Day"] = day[obj_au_settings.ScheduledInstallationDay]
 1113         # Scheduled Installation Time requires special handling to return the time
 1114         # in the right format
 1115         if obj_au_settings.ScheduledInstallationTime < 10:
 1116             ret["Scheduled Time"] = "0{}:00".format(
 1117                 obj_au_settings.ScheduledInstallationTime
 1118             )
 1119         else:
 1120             ret["Scheduled Time"] = "{}:00".format(
 1121                 obj_au_settings.ScheduledInstallationTime
 1122             )
 1123 
 1124     return ret
 1125 
 1126 
 1127 def _get_msupdate_status():
 1128     """
 1129     Check to see if Microsoft Update is Enabled
 1130     Return Boolean
 1131     """
 1132     # To get the status of Microsoft Update we actually have to check the
 1133     # Microsoft Update Service Manager
 1134     # Initialize the PyCom system
 1135     with salt.utils.winapi.Com():
 1136         # Create a ServiceManager Object
 1137         obj_sm = win32com.client.Dispatch("Microsoft.Update.ServiceManager")
 1138 
 1139         # Return a collection of loaded Services
 1140         col_services = obj_sm.Services
 1141 
 1142         # Loop through the collection to find the Microsoft Udpate Service
 1143         # If it exists return True otherwise False
 1144         for service in col_services:
 1145             if service.name == "Microsoft Update":
 1146                 return True
 1147 
 1148     return False
 1149 
 1150 
 1151 def get_needs_reboot():
 1152     """
 1153     Determines if the system needs to be rebooted.
 1154 
 1155     Returns:
 1156 
 1157         bool: ``True`` if the system requires a reboot, otherwise ``False``
 1158 
 1159     CLI Examples:
 1160 
 1161     .. code-block:: bash
 1162 
 1163         salt '*' win_wua.get_needs_reboot
 1164     """
 1165     return salt.utils.win_update.needs_reboot()