"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()