ansible / ansible-modules-extras

Ansible extra modules - these modules ship with ansible
948 stars 1.46k forks source link

win_updates Not working on localized Windows Server 2012R2 (russian) #3676

Closed dssdss closed 7 years ago

dssdss commented 7 years ago
ISSUE TYPE
COMPONENT NAME

win_updates

ANSIBLE VERSION
ansible 2.2.0.0
  config file = /home/testuser0/ansible/ansible.cfg
  configured module search path = Default w/o overrides
CONFIGURATION
OS / ENVIRONMENT

OS I'm running from:

Debian Jessie (8.6)
uname -a
Linux wmgm 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt25-2+deb8u3 (2016-07-02) x86_64 GNU/Linux

OS I'm managing:

PS C:\Users\testuser> gwmi win32_operatingsystem | select caption, OSArchitecture, Version, BuildNumber | fl

caption        : Microsoft Windows Server 2012 R2 Standard
OSArchitecture : 64-разрядная
Version        : 6.3.9600
BuildNumber    : 9600
PS C:\Users\testuser> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      4.0
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.34014
BuildVersion                   6.3.9600.17090
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion      2.2

Localization:

C:\Windows\system32>dism /online /get-intl

Deployment Image Servicing and Management tool
Version: 6.3.9600.17031

Image Version: 6.3.9600.17031

Reporting online international settings.

Default system UI language : ru-RU
The UI language fallback is : en-US
System locale : ru-RU
Default time zone : Russian Standard Time
Active keyboard(s) : 0419:00000419, 0409:00000409
Keyboard layered driver : PC/AT Enhanced Keyboard (101/102-Key)

Installed language(s): en-US
  Type : Fully localized language.
Installed language(s): ru-RU
  Type : Partially localized language, MUI type.
  Fallback Languages en-US
SUMMARY
STEPS TO REPRODUCE

I tried to install windows updates on localized russian windows server 2012R2 (ru_windows_server_2012_r2_vl_with_update_x64_dvd_6052827.iso) via win_updates module, but I got error:

"Definition": "System.Management.Automation.JobDefinition", "InstanceId": "78bcd293-1626-4999-a3ad-4fc9ab6705ae", "Name": "ansible-win-updates", "Parameters": "System.Management.Automation.Runspaces.CommandParameterCollection"}, "JobTriggers": [], "Name": "ansible-win-updates", "Options": {"DoNotAllowDemandStart": false, "IdleDuration": "00:10:00", "IdleTimeout": "01:00:00", "JobDefinition": "Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition", "MultipleInstancePolicy": 1, "RestartOnIdleResume": false, "RunElevated": true, "RunWithoutNetwork": true, "ShowInTaskScheduler": true, "StartIfNotIdle": true, "StartIfOnBatteries": false, "StopIfGoingOffIdle": false, "StopIfGoingOnBatteries": true, "WakeToRun": false}, "PSExecutionArgs": "-NoLogo -NonInteractive -WindowStyle Hidden -Command \"Import-Module PSScheduledJob; $jobDef = [Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition]::LoadFromStore('ansible-win-updates', 'C:\\Users\\testuser\\AppData\\Local\\Microsoft\\Windows\\PowerShell\\ScheduledJobs'); $jobDef.Run()\"", "PSExecutionPath": "powershell.exe"}}, "failed": true, "msg": "An error occurred while registering scheduled job definition ansible-win-updates to the Windows Task Scheduler.  The Task Scheduler error is: Cannot create a file when that file already exists. (Exception from HRESULT: 0x800700B7)."

I've installed english Windows Server 2012r2 (en_windows_server_2012_r2_vl_with_update_x64_dvd_6052766.iso) and put it into the same OU in Active Directory - win_updates works perfect!!!

If you want to reproduce this bug I can help you to deploy localized windows version, or I can send it to you as a VmWare virtual machine...

~/ansible/group_vars/all.yml:

ansible_user: testuser@TESTDOMAIN.LAN
ansible_port: 5985
ansible_connection: winrm
ansible_listener: http
ansible_winrm_server_cert_validation: ignore

~/ansible/hosts:

[test]
dssw2012r2.testdomain.lan

~/ansible/update_t.yml:

---
- name: Update Installation and reboot for test servers
  hosts: test

  tasks:
  - include: roles/service/tasks/install_updates.yml
  - include: roles/service/tasks/reboot.yml
    when: check_finish.reboot_required == true
  - pause: minutes=5

~/ansible/roles/service/tasks/install_updates.yml:

---
- name: install (all) updates
  win_updates:
   category_names:
     - Application
     - Connectors
     - DefinitionUpdates
     - DeveloperKits
     - FeaturePacks
     - Guidance
     - ServicePacks
     - Tools
     - UpdateRollups
     - CriticalUpdates
     - SecurityUpdates
   log_path:
    c:/Scripts/ansible_wu.txt
  register: check_finish
EXPECTED RESULTS

c:/Scripts/ansible_wu.txt:

2016-12-06 18:40:59Z Arguments: System.Collections.Hashtable | out-string
2016-12-06 18:40:59Z OS Version: 
Major  Minor  Build  Revision
-----  -----  -----  --------
6      3      9600   0       

2016-12-06 18:40:59Z Running as user: TESTDOMAIN\testuser
2016-12-06 18:40:59Z Powershell version: 
Name                           Value                                           
----                           -----                                           
PSVersion                      4.0                                             
WSManStackVersion              3.0                                             
SerializationVersion           1.1.0.1                                         
CLRVersion                     4.0.30319.34014                                 
BuildVersion                   6.3.9600.17090                                  
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}                            
PSRemotingProtocolVersion      2.2                                             

2016-12-06 18:40:59Z Starting scheduled job with args: 
Name                           Value                                                                                                                                                                                                                                                                        
----                           -----                                                                                                                                                                                                                                                                        
_ansible_debug                 False
_ansible_version               2.2.0.0
_ansible_diff                  False
category_names                 {Application, Connectors, DefinitionUpdates, DeveloperKits...}  
_ansible_syslog_facility       LOG_USER                                                                                                                                                                                                                                                                     
_ansible_check_mode            False                                                                                                                                                                                                                                                                        
_ansible_selinux_special_fs    {fuse, nfs, vboxsf, ramfs}                                                                                                                                                                                                                                                   
_ansible_module_name           win_updates                                                                                                                                                                                                                                                                  
log_path                       c:/Scripts/ansible_wu.txt                                                                                                                                                                                                                                                    
_ansible_no_log                False                                                                                                                                                                                                                                                                        
_ansible_verbosity             0                                                                                                                                                                                                                                                                            

2016-12-06 18:40:59Z Registering scheduled job with args 
Name                           Value                                                                                                                                                                                                                                                                        
----                           -----                                                                                                                                                                                                                                                                        
ScheduledJobOption             {RunElevated}                                                                                                                                                                                                                                                                
ArgumentList                   {System.Collections.Hashtable}                                                                                                                                                                                                                                               
InitializationScript           ...                                                                                                                                                                                                                                                                          
Name                           ansible-win-updates                                                                                                                                                                                                                                                          
ScriptBlock                    ...                                                                                                                                                                                                                                                                          
ErrorAction                    Stop                     
ACTUAL RESULTS
root@wmgm:~/ansible# ansible-playbook update_t.yml -i hosts 

PLAY [Update Installation and reboot for test servers] *************************

TASK [setup] *******************************************************************
ok: [dssw2012r2.testdomain.lan]

TASK [Set zabbix maintenance for portal.nalog.dmz] *****************************
skipping: [dssw2012r2.testdomain.lan]

TASK [Set zabbix maintenance] **************************************************
ok: [dssw2012r2.testdomain.lan -> 127.0.0.1]

TASK [install (all) updates] ***************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: +               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fatal: [dssw2012r2.testdomain.lan]: FAILED! => {"changed": false, "error_record": {"CategoryInfo": {"Activity": "Register-ScheduledJob", "Category": 7, "Reason": "ScheduledJobException", "TargetName": "Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition", "TargetType": "ScheduledJobDefinition"}, "ErrorDetails": null, "Exception": {"Data": {}, "HResult": -2146233087, "HelpLink": null, "InnerException": {"Data": "System.Collections.ListDictionaryInternal", "ErrorCode": -2147024713, "HResult": -2147024713, "HelpLink": null, "InnerException": null, "Message": "Cannot create a file when that file already exists. (Exception from HRESULT: 0x800700B7)", "Source": "Microsoft.PowerShell.ScheduledJob", "StackTrace": "   at TaskScheduler.ITaskFolder.RegisterTaskDefinition(String Path, ITaskDefinition pDefinition, Int32 flags, Object UserId, Object password, _TASK_LOGON_TYPE LogonType, Object sddl)\r\n   at Microsoft.PowerShell.ScheduledJob.ScheduledJobWTS.CreateTask(ScheduledJobDefinition definition)\r\n   at Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition.AddToWTS()\r\n   at Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition.Register()", "TargetSite": "TaskScheduler.IRegisteredTask RegisterTaskDefinition(System.String, TaskScheduler.ITaskDefinition, Int32, System.Object, System.Object, TaskScheduler._TASK_LOGON_TYPE, System.Object)"}, "Message": "An error occurred while registering scheduled job definition ansible-win-updates to the Windows Task Scheduler.  The Task Scheduler error is: Cannot create a file when that file already exists. (Exception from HRESULT: 0x800700B7).", "Source": "Microsoft.PowerShell.ScheduledJob", "StackTrace": "   at Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition.Register()\r\n   at Microsoft.PowerShell.ScheduledJob.RegisterScheduledJobCommand.ProcessRecord()", "TargetSite": {"Attributes": 134, "CallingConvention": 33, "ContainsGenericParameters": false, "CustomAttributes": "", "DeclaringType": "Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition", "IsAbstract": false, "IsAssembly": false, "IsConstructor": false, "IsFamily": false, "IsFamilyAndAssembly": false, "IsFamilyOrAssembly": false, "IsFinal": false, "IsGenericMethod": false, "IsGenericMethodDefinition": false, "IsHideBySig": true, "IsPrivate": false, "IsPublic": true, "IsSecurityCritical": true, "IsSecuritySafeCritical": false, "IsSecurityTransparent": false, "IsSpecialName": false, "IsStatic": false, "IsVirtual": false, "MemberType": 8, "MetadataToken": 100663399, "MethodHandle": "System.RuntimeMethodHandle", "MethodImplementationFlags": 0, "Module": "Microsoft.PowerShell.ScheduledJob.dll", "Name": "Register", "ReflectedType": "Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition", "ReturnParameter": "Void ", "ReturnType": "void", "ReturnTypeCustomAttributes": "Void "}}, "FullyQualifiedErrorId": "CantRegisterScheduledJobDefinition,Microsoft.PowerShell.ScheduledJob.RegisterScheduledJobCommand", "InvocationInfo": {"BoundParameters": {}, "CommandOrigin": 1, "DisplayScriptPosition": null, "ExpectingInput": false, "HistoryId": 1, "InvocationName": "Register-ScheduledJob", "Line": "  $schedjob = Register-ScheduledJob @rsj_args\n", "MyCommand": {"CommandType": 8, "DefaultParameterSet": "ScriptBlock", "Definition": "\r\nRegister-ScheduledJob [-Name] <string> [-ScriptBlock] <scriptblock> [-Trigger <ScheduledJobTrigger[]>] [-InitializationScript <scriptblock>] [-RunAs32] [-Credential <pscredential>] [-Authentication <AuthenticationMechanism>] [-ScheduledJobOption <ScheduledJobOptions>] [-ArgumentList <Object[]>] [-MaxResultCount <int>] [-RunNow] [-WhatIf] [-Confirm] [<CommonParameters>]\r\n\r\nRegister-ScheduledJob [-Name] <string> [-FilePath] <string> [-Trigger <ScheduledJobTrigger[]>] [-InitializationScript <scriptblock>] [-RunAs32] [-Credential <pscredential>] [-Authentication <AuthenticationMechanism>] [-ScheduledJobOption <ScheduledJobOptions>] [-ArgumentList <Object[]>] [-MaxResultCount <int>] [-RunNow] [-WhatIf] [-Confirm] [<CommonParameters>]\r\n", "HelpFile": "Microsoft.PowerShell.ScheduledJob.dll-Help.xml", "ImplementingType": "Microsoft.PowerShell.ScheduledJob.RegisterScheduledJobCommand", "Module": "PSScheduledJob", "ModuleName": "PSScheduledJob", "Name": "Register-ScheduledJob", "Noun": "ScheduledJob", "Options": 1, "OutputType": "Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition", "PSSnapIn": null, "ParameterSets": "[-Name] <string> [-ScriptBlock] <scriptblock> [-Trigger <ScheduledJobTrigger[]>] [-InitializationScript <scriptblock>] [-RunAs32] [-Credential <pscredential>] [-Authentication <AuthenticationMechanism>] [-ScheduledJobOption <ScheduledJobOptions>] [-ArgumentList <Object[]>] [-MaxResultCount <int>] [-RunNow] [-WhatIf] [-Confirm] [<CommonParameters>] [-Name] <string> [-FilePath] <string> [-Trigger <ScheduledJobTrigger[]>] [-InitializationScript <scriptblock>] [-RunAs32] [-Credential <pscredential>] [-Authentication <AuthenticationMechanism>] [-ScheduledJobOption <ScheduledJobOptions>] [-ArgumentList <Object[]>] [-MaxResultCount <int>] [-RunNow] [-WhatIf] [-Confirm] [<CommonParameters>]", "Parameters": "System.Collections.Generic.Dictionary`2[System.String,System.Management.Automation.ParameterMetadata]", "RemotingCapability": 1, "Verb": "Register", "Visibility": 0}, "OffsetInLine": 15, "PSCommandPath": "C:\\Users\\testuser\\AppData\\Local\\Temp\\ansible-tmp-1481043370.46-211730871360256\\win_updates.ps1", "PSScriptRoot": "C:\\Users\\testuser\\AppData\\Local\\Temp\\ansible-tmp-1481043370.46-211730871360256", "PipelineLength": 0, "PipelinePosition": 0, "PositionMessage": "At C:\\Users\\testuser\\AppData\\Local\\Temp\\ansible-tmp-1481043370.46-211730871360256\\win_updates.ps1:558 char:15\r\n+   $schedjob = Register-ScheduledJob @rsj_args\r\n+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", "ScriptLineNumber": 558, "ScriptName": "C:\\Users\\testuser\\AppData\\Local\\Temp\\ansible-tmp-1481043370.46-211730871360256\\win_updates.ps1", "UnboundArguments": []}, "PSMessageDetails": null, "PipelineIterationInfo": [], "ScriptStackTrace": "at RunAsScheduledJob, C:\\Users\\testuser\\AppData\\Local\\Temp\\ansible-tmp-1481043370.46-211730871360256\\win_updates.ps1: line 558\r\nat <ScriptBlock>, C:\\Users\\testuser\\AppData\\Local\\Temp\\ansible-tmp-1481043370.46-211730871360256\\win_updates.ps1: line 666\r\nat <ScriptBlock>, <No file>: line 4", "TargetObject": {"Command": "\n    Param(\n    [hashtable]$boundparms=@{},\n    [Object[]]$unboundargs=$()\n    )\n\n    Set-StrictMode -Version 2\n\n    $ErrorActionPreference = \"Stop\"\n    $DebugPreference = \"Continue\"\n    $FormatEnumerationLimit = -1 # prevent out-string et al from truncating collection dumps\n\n    # set this as a global for the Write-DebugLog function\n    $log_path = $boundparms['log_path']\n\n    Write-DebugLog \"Scheduled job started with boundparms $($boundparms | out-string) and unboundargs $($unboundargs | out-string)\"\n\n    # FUTURE: elevate this to module arg validation once we have it\n    Function MapCategoryNameToGuid {\n        Param([string] $category_name)\n\n        $category_guid = switch -exact ($category_name) {\n            # as documented by TechNet @ https://technet.microsoft.com/en-us/library/ff730937.aspx\n            \"Application\" {\"5C9376AB-8CE6-464A-B136-22113DD69801\"}\n            \"Connectors\" {\"434DE588-ED14-48F5-8EED-A15E09A991F6\"}\n            \"CriticalUpdates\" {\"E6CF1350-C01B-414D-A61F-263D14D133B4\"}\n            \"DefinitionUpdates\" {\"E0789628-CE08-4437-BE74-2495B842F43B\"}\n            \"DeveloperKits\" {\"E140075D-8433-45C3-AD87-E72345B36078\"}\n            \"FeaturePacks\" {\"B54E7D24-7ADD-428F-8B75-90A396FA584F\"}\n            \"Guidance\" {\"9511D615-35B2-47BB-927F-F73D8E9260BB\"}\n            \"SecurityUpdates\" {\"0FA1201D-4330-4FA8-8AE9-B877473B6441\"}\n            \"ServicePacks\" {\"68C5B0A3-D1A6-4553-AE49-01D3A7827828\"}\n            \"Tools\" {\"B4832BD8-E735-4761-8DAF-37F882276DAB\"}\n            \"UpdateRollups\" {\"28BC880E-0592-4CBF-8F95-C79B17911D5F\"}\n            \"Updates\" {\"CD5FFD1E-E932-4E3A-BF74-18BF0B1BBD83\"}\n            default { throw \"Unknown category_name $category_name, must be one of (Application,Connectors,CriticalUpdates,DefinitionUpdates,DeveloperKits,FeaturePacks,Guidance,SecurityUpdates,ServicePacks,Tools,UpdateRollups,Updates)\" }\n        }\n\n        return $category_guid\n    }\n\n    Function DoWindowsUpdate {\n        Param(\n        [string[]]$category_names=@(\"CriticalUpdates\",\"SecurityUpdates\",\"UpdateRollups\"),\n        [ValidateSet(\"installed\", \"searched\")]\n        [string]$state=\"installed\",\n        [bool]$_ansible_check_mode=$false\n        )\n\n        $is_check_mode = $($state -eq \"searched\") -or $_ansible_check_mode\n\n        $category_guids = $category_names | % { MapCategoryNameToGUID $_ }\n\n        $update_status = @{ changed = $false }\n\n        Write-DebugLog \"Creating Windows Update session...\"\n        $session = New-Object -ComObject Microsoft.Update.Session\n\n        Write-DebugLog \"Create Windows Update searcher...\"\n        $searcher = $session.CreateUpdateSearcher()\n\n        # OR is only allowed at the top-level, so we have to repeat base criteria inside\n        # FUTURE: change this to client-side filtered?\n        $criteriabase = \"IsInstalled = 0\"\n        $criteria_list = $category_guids | % { \"($criteriabase AND CategoryIDs contains '$_')\" }\n\n        $criteria = [string]::Join(\" OR \", $criteria_list)\n\n        Write-DebugLog \"Search criteria: $criteria\"\n\n        Write-DebugLog \"Searching for updates to install in category IDs $category_guids...\"\n        $searchresult = $searcher.Search($criteria)\n\n        Write-DebugLog \"Creating update collection...\"\n    \n        $updates_to_install = New-Object -ComObject Microsoft.Update.UpdateColl\n\n        Write-DebugLog \"Found $($searchresult.Updates.Count) updates\"\n\n        $update_status.updates = @{ }\n\n        # FUTURE: add further filtering options\n        foreach($update in $searchresult.Updates) {\n          if(-Not $update.EulaAccepted) {\n            Write-DebugLog \"Accepting EULA for $($update.Identity.UpdateID)\"\n            $update.AcceptEula()\n          }\n\n          if($update.IsHidden) {\n            Write-DebugLog \"Skipping hidden update $($update.Title)\"\n            continue\n          }\n\n          Write-DebugLog \"Adding update $($update.Identity.UpdateID) - $($update.Title)\"\n          $res = $updates_to_install.Add($update)\n\n          $update_status.updates[$update.Identity.UpdateID] = @{\n            title = $update.Title\n            # TODO: pluck the first KB out (since most have just one)?\n            kb = $update.KBArticleIDs\n            id = $update.Identity.UpdateID\n            installed = $false\n          }\n        }\n\n        Write-DebugLog \"Calculating pre-install reboot requirement...\"\n\n        # calculate this early for check mode, and to see if we should allow updates to continue\n        $sysinfo = New-Object -ComObject Microsoft.Update.SystemInfo\n        $update_status.reboot_required = $sysinfo.RebootRequired\n        $update_status.found_update_count = $updates_to_install.Count\n        $update_status.installed_update_count = 0\n\n        # bail out here for check mode  \n        if($is_check_mode -eq $true) { \n          Write-DebugLog \"Check mode; exiting...\"\n          Write-DebugLog \"Return value: $($update_status | out-string)\"\n\n          if($updates_to_install.Count -gt 0) { $update_status.changed = $true }\n          return $update_status \n        }\n\n        if($updates_to_install.Count -gt 0) {   \n          if($update_status.reboot_required) { \n            throw \"A reboot is required before more updates can be installed.\"\n          }\n          else {\n            Write-DebugLog \"No reboot is pending...\"\n          }\n          Write-DebugLog \"Downloading updates...\" \n        }\n\n        foreach($update in $updates_to_install) {\n            if($update.IsDownloaded) { \n                Write-DebugLog \"Update $($update.Identity.UpdateID) already downloaded, skipping...\"\n                continue \n            }\n            Write-DebugLog \"Creating downloader object...\"\n            $dl = $session.CreateUpdateDownloader()\n            Write-DebugLog \"Creating download collection...\"\n            $dl.Updates = New-Object -ComObject Microsoft.Update.UpdateColl\n            Write-DebugLog \"Adding update $($update.Identity.UpdateID)\"\n            $res = $dl.Updates.Add($update)\n            Write-DebugLog \"Downloading update $($update.Identity.UpdateID)...\"\n            $download_result = $dl.Download()\n            # FUTURE: configurable download retry\n            if($download_result.ResultCode -ne 2) { # OperationResultCode orcSucceeded\n                throw \"Failed to download update $($update.Identity.UpdateID)\"\n            }\n        }\n\n        if($updates_to_install.Count -lt 1 ) { return $update_status }\n\n        Write-DebugLog \"Installing updates...\"\n\n        # install as a batch so the reboot manager will suppress intermediate reboots\n        Write-DebugLog \"Creating installer object...\"\n        $inst = $session.CreateUpdateInstaller()\n        Write-DebugLog \"Creating install collection...\"\n        $inst.Updates = New-Object -ComObject Microsoft.Update.UpdateColl\n\n        foreach($update in $updates_to_install) {\n            Write-DebugLog \"Adding update $($update.Identity.UpdateID)\"\n            $res = $inst.Updates.Add($update)\n        }\n\n        # FUTURE: use BeginInstall w/ progress reporting so we can at least log intermediate install results\n        Write-DebugLog \"Installing updates...\"\n        $install_result = $inst.Install()\n\n        $update_success_count = 0\n        $update_fail_count = 0\n\n        # WU result API requires us to index in to get the install results\n        $update_index = 0\n\n        foreach($update in $updates_to_install) {\n          $update_result = $install_result.GetUpdateResult($update_index)\n          $update_resultcode = $update_result.ResultCode\n          $update_hresult = $update_result.HResult\n\n          $update_index++\n\n          $update_dict = $update_status.updates[$update.Identity.UpdateID]\n\n          if($update_resultcode -eq 2) { # OperationResultCode orcSucceeded\n            $update_success_count++\n            $update_dict.installed = $true\n            Write-DebugLog \"Update $($update.Identity.UpdateID) succeeded\"\n          }\n          else {\n            $update_fail_count++\n            $update_dict.installed = $false\n            $update_dict.failed = $true\n            $update_dict.failure_hresult_code = $update_hresult\n            Write-DebugLog \"Update $($update.Identity.UpdateID) failed resultcode $update_hresult hresult $update_hresult\"\n          }\n\n        }\n\n        if($update_fail_count -gt 0) {  \n            $update_status.failed = $true\n            $update_status.msg=\"Failed to install one or more updates\"\n        }\n        else { $update_status.changed = $true }\n\n        Write-DebugLog \"Performing post-install reboot requirement check...\"\n\n        # recalculate reboot status after installs\n        $sysinfo = New-Object -ComObject Microsoft.Update.SystemInfo\n        $update_status.reboot_required = $sysinfo.RebootRequired\n        $update_status.installed_update_count = $update_success_count\n        $update_status.failed_update_count = $update_fail_count\n\n        Write-DebugLog \"Return value: $($update_status | out-string)\"\n\n        return $update_status\n    }\n\n    Try { \n        # job system adds a bunch of cruft to top-level dict, so we have to send a sub-dict\n        return @{ job_output = DoWindowsUpdate @boundparms }\n    }\n    Catch {\n        $excep = $_\n        Write-DebugLog \"Fatal exception: $($excep.Exception.Message) at $($excep.ScriptStackTrace)\"\n        return @{ job_output = @{ failed=$true;error=$excep.Exception.Message;location=$excep.ScriptStackTrace } }\n    }\n", "Credential": null, "Definition": {"Command": "\n    Param(\n    [hashtable]$boundparms=@{},\n    [Object[]]$unboundargs=$()\n    )\n\n    Set-StrictMode -Version 2\n\n    $ErrorActionPreference = \"Stop\"\n    $DebugPreference = \"Continue\"\n    $FormatEnumerationLimit = -1 # prevent out-string et al from truncating collection dumps\n\n    # set this as a global for the Write-DebugLog function\n    $log_path = $boundparms['log_path']\n\n    Write-DebugLog \"Scheduled job started with boundparms $($boundparms | out-string) and unboundargs $($unboundargs | out-string)\"\n\n    # FUTURE: elevate this to module arg validation once we have it\n    Function MapCategoryNameToGuid {\n        Param([string] $category_name)\n\n        $category_guid = switch -exact ($category_name) {\n            # as documented by TechNet @ https://technet.microsoft.com/en-us/library/ff730937.aspx\n            \"Application\" {\"5C9376AB-8CE6-464A-B136-22113DD69801\"}\n            \"Connectors\" {\"434DE588-ED14-48F5-8EED-A15E09A991F6\"}\n            \"CriticalUpdates\" {\"E6CF1350-C01B-414D-A61F-263D14D133B4\"}\n            \"DefinitionUpdates\" {\"E0789628-CE08-4437-BE74-2495B842F43B\"}\n            \"DeveloperKits\" {\"E140075D-8433-45C3-AD87-E72345B36078\"}\n            \"FeaturePacks\" {\"B54E7D24-7ADD-428F-8B75-90A396FA584F\"}\n            \"Guidance\" {\"9511D615-35B2-47BB-927F-F73D8E9260BB\"}\n            \"SecurityUpdates\" {\"0FA1201D-4330-4FA8-8AE9-B877473B6441\"}\n            \"ServicePacks\" {\"68C5B0A3-D1A6-4553-AE49-01D3A7827828\"}\n            \"Tools\" {\"B4832BD8-E735-4761-8DAF-37F882276DAB\"}\n            \"UpdateRollups\" {\"28BC880E-0592-4CBF-8F95-C79B17911D5F\"}\n            \"Updates\" {\"CD5FFD1E-E932-4E3A-BF74-18BF0B1BBD83\"}\n            default { throw \"Unknown category_name $category_name, must be one of (Application,Connectors,CriticalUpdates,DefinitionUpdates,DeveloperKits,FeaturePacks,Guidance,SecurityUpdates,ServicePacks,Tools,UpdateRollups,Updates)\" }\n        }\n\n        return $category_guid\n    }\n\n    Function DoWindowsUpdate {\n        Param(\n        [string[]]$category_names=@(\"CriticalUpdates\",\"SecurityUpdates\",\"UpdateRollups\"),\n        [ValidateSet(\"installed\", \"searched\")]\n        [string]$state=\"installed\",\n        [bool]$_ansible_check_mode=$false\n        )\n\n        $is_check_mode = $($state -eq \"searched\") -or $_ansible_check_mode\n\n        $category_guids = $category_names | % { MapCategoryNameToGUID $_ }\n\n        $update_status = @{ changed = $false }\n\n        Write-DebugLog \"Creating Windows Update session...\"\n        $session = New-Object -ComObject Microsoft.Update.Session\n\n        Write-DebugLog \"Create Windows Update searcher...\"\n        $searcher = $session.CreateUpdateSearcher()\n\n        # OR is only allowed at the top-level, so we have to repeat base criteria inside\n        # FUTURE: change this to client-side filtered?\n        $criteriabase = \"IsInstalled = 0\"\n        $criteria_list = $category_guids | % { \"($criteriabase AND CategoryIDs contains '$_')\" }\n\n        $criteria = [string]::Join(\" OR \", $criteria_list)\n\n        Write-DebugLog \"Search criteria: $criteria\"\n\n        Write-DebugLog \"Searching for updates to install in category IDs $category_guids...\"\n        $searchresult = $searcher.Search($criteria)\n\n        Write-DebugLog \"Creating update collection...\"\n    \n        $updates_to_install = New-Object -ComObject Microsoft.Update.UpdateColl\n\n        Write-DebugLog \"Found $($searchresult.Updates.Count) updates\"\n\n        $update_status.updates = @{ }\n\n        # FUTURE: add further filtering options\n        foreach($update in $searchresult.Updates) {\n          if(-Not $update.EulaAccepted) {\n            Write-DebugLog \"Accepting EULA for $($update.Identity.UpdateID)\"\n            $update.AcceptEula()\n          }\n\n          if($update.IsHidden) {\n            Write-DebugLog \"Skipping hidden update $($update.Title)\"\n            continue\n          }\n\n          Write-DebugLog \"Adding update $($update.Identity.UpdateID) - $($update.Title)\"\n          $res = $updates_to_install.Add($update)\n\n          $update_status.updates[$update.Identity.UpdateID] = @{\n            title = $update.Title\n            # TODO: pluck the first KB out (since most have just one)?\n            kb = $update.KBArticleIDs\n            id = $update.Identity.UpdateID\n            installed = $false\n          }\n        }\n\n        Write-DebugLog \"Calculating pre-install reboot requirement...\"\n\n        # calculate this early for check mode, and to see if we should allow updates to continue\n        $sysinfo = New-Object -ComObject Microsoft.Update.SystemInfo\n        $update_status.reboot_required = $sysinfo.RebootRequired\n        $update_status.found_update_count = $updates_to_install.Count\n        $update_status.installed_update_count = 0\n\n        # bail out here for check mode  \n        if($is_check_mode -eq $true) { \n          Write-DebugLog \"Check mode; exiting...\"\n          Write-DebugLog \"Return value: $($update_status | out-string)\"\n\n          if($updates_to_install.Count -gt 0) { $update_status.changed = $true }\n          return $update_status \n        }\n\n        if($updates_to_install.Count -gt 0) {   \n          if($update_status.reboot_required) { \n            throw \"A reboot is required before more updates can be installed.\"\n          }\n          else {\n            Write-DebugLog \"No reboot is pending...\"\n          }\n          Write-DebugLog \"Downloading updates...\" \n        }\n\n        foreach($update in $updates_to_install) {\n            if($update.IsDownloaded) { \n                Write-DebugLog \"Update $($update.Identity.UpdateID) already downloaded, skipping...\"\n                continue \n            }\n            Write-DebugLog \"Creating downloader object...\"\n            $dl = $session.CreateUpdateDownloader()\n            Write-DebugLog \"Creating download collection...\"\n            $dl.Updates = New-Object -ComObject Microsoft.Update.UpdateColl\n            Write-DebugLog \"Adding update $($update.Identity.UpdateID)\"\n            $res = $dl.Updates.Add($update)\n            Write-DebugLog \"Downloading update $($update.Identity.UpdateID)...\"\n            $download_result = $dl.Download()\n            # FUTURE: configurable download retry\n            if($download_result.ResultCode -ne 2) { # OperationResultCode orcSucceeded\n                throw \"Failed to download update $($update.Identity.UpdateID)\"\n            }\n        }\n\n        if($updates_to_install.Count -lt 1 ) { return $update_status }\n\n        Write-DebugLog \"Installing updates...\"\n\n        # install as a batch so the reboot manager will suppress intermediate reboots\n        Write-DebugLog \"Creating installer object...\"\n        $inst = $session.CreateUpdateInstaller()\n        Write-DebugLog \"Creating install collection...\"\n        $inst.Updates = New-Object -ComObject Microsoft.Update.UpdateColl\n\n        foreach($update in $updates_to_install) {\n            Write-DebugLog \"Adding update $($update.Identity.UpdateID)\"\n            $res = $inst.Updates.Add($update)\n        }\n\n        # FUTURE: use BeginInstall w/ progress reporting so we can at least log intermediate install results\n        Write-DebugLog \"Installing updates...\"\n        $install_result = $inst.Install()\n\n        $update_success_count = 0\n        $update_fail_count = 0\n\n        # WU result API requires us to index in to get the install results\n        $update_index = 0\n\n        foreach($update in $updates_to_install) {\n          $update_result = $install_result.GetUpdateResult($update_index)\n          $update_resultcode = $update_result.ResultCode\n          $update_hresult = $update_result.HResult\n\n          $update_index++\n\n          $update_dict = $update_status.updates[$update.Identity.UpdateID]\n\n          if($update_resultcode -eq 2) { # OperationResultCode orcSucceeded\n            $update_success_count++\n            $update_dict.installed = $true\n            Write-DebugLog \"Update $($update.Identity.UpdateID) succeeded\"\n          }\n          else {\n            $update_fail_count++\n            $update_dict.installed = $false\n            $update_dict.failed = $true\n            $update_dict.failure_hresult_code = $update_hresult\n            Write-DebugLog \"Update $($update.Identity.UpdateID) failed resultcode $update_hresult hresult $update_hresult\"\n          }\n\n        }\n\n        if($update_fail_count -gt 0) {  \n            $update_status.failed = $true\n            $update_status.msg=\"Failed to install one or more updates\"\n        }\n        else { $update_status.changed = $true }\n\n        Write-DebugLog \"Performing post-install reboot requirement check...\"\n\n        # recalculate reboot status after installs\n        $sysinfo = New-Object -ComObject Microsoft.Update.SystemInfo\n        $update_status.reboot_required = $sysinfo.RebootRequired\n        $update_status.installed_update_count = $update_success_count\n        $update_status.failed_update_count = $update_fail_count\n\n        Write-DebugLog \"Return value: $($update_status | out-string)\"\n\n        return $update_status\n    }\n\n    Try { \n        # job system adds a bunch of cruft to top-level dict, so we have to send a sub-dict\n        return @{ job_output = DoWindowsUpdate @boundparms }\n    }\n    Catch {\n        $excep = $_\n        Write-DebugLog \"Fatal exception: $($excep.Exception.Message) at $($excep.ScriptStackTrace)\"\n        return @{ job_output = @{ failed=$true;error=$excep.Exception.Message;location=$excep.ScriptStackTrace } }\n    }\n", "CommandInfo": null, "InstanceId": "3de2d296-00a5-471c-aced-6559132eea09", "JobSourceAdapterType": "Microsoft.PowerShell.ScheduledJob.ScheduledJobSourceAdapter", "JobSourceAdapterTypeName": "ScheduledJobSourceAdapter", "ModuleName": "PSScheduledJob", "Name": "ansible-win-updates"}, "Enabled": true, "ExecutionHistoryLength": 32, "GlobalId": "be033c98-3718-44a9-a8f9-59d4a045e0f7", "Id": 1, "InvocationInfo": {"Command": "\n    Param(\n    [hashtable]$boundparms=@{},\n    [Object[]]$unboundargs=$()\n    )\n\n    Set-StrictMode -Version 2\n\n    $ErrorActionPreference = \"Stop\"\n    $DebugPreference = \"Continue\"\n    $FormatEnumerationLimit = -1 # prevent out-string et al from truncating collection dumps\n\n    # set this as a global for the Write-DebugLog function\n    $log_path = $boundparms['log_path']\n\n    Write-DebugLog \"Scheduled job started with boundparms $($boundparms | out-string) and unboundargs $($unboundargs | out-string)\"\n\n    # FUTURE: elevate this to module arg validation once we have it\n    Function MapCategoryNameToGuid {\n        Param([string] $category_name)\n\n        $category_guid = switch -exact ($category_name) {\n            # as documented by TechNet @ https://technet.microsoft.com/en-us/library/ff730937.aspx\n            \"Application\" {\"5C9376AB-8CE6-464A-B136-22113DD69801\"}\n            \"Connectors\" {\"434DE588-ED14-48F5-8EED-A15E09A991F6\"}\n            \"CriticalUpdates\" {\"E6CF1350-C01B-414D-A61F-263D14D133B4\"}\n            \"DefinitionUpdates\" {\"E0789628-CE08-4437-BE74-2495B842F43B\"}\n            \"DeveloperKits\" {\"E140075D-8433-45C3-AD87-E72345B36078\"}\n            \"FeaturePacks\" {\"B54E7D24-7ADD-428F-8B75-90A396FA584F\"}\n            \"Guidance\" {\"9511D615-35B2-47BB-927F-F73D8E9260BB\"}\n            \"SecurityUpdates\" {\"0FA1201D-4330-4FA8-8AE9-B877473B6441\"}\n            \"ServicePacks\" {\"68C5B0A3-D1A6-4553-AE49-01D3A7827828\"}\n            \"Tools\" {\"B4832BD8-E735-4761-8DAF-37F882276DAB\"}\n            \"UpdateRollups\" {\"28BC880E-0592-4CBF-8F95-C79B17911D5F\"}\n            \"Updates\" {\"CD5FFD1E-E932-4E3A-BF74-18BF0B1BBD83\"}\n            default { throw \"Unknown category_name $category_name, must be one of (Application,Connectors,CriticalUpdates,DefinitionUpdates,DeveloperKits,FeaturePacks,Guidance,SecurityUpdates,ServicePacks,Tools,UpdateRollups,Updates)\" }\n        }\n\n        return $category_guid\n    }\n\n    Function DoWindowsUpdate {\n        Param(\n        [string[]]$category_names=@(\"CriticalUpdates\",\"SecurityUpdates\",\"UpdateRollups\"),\n        [ValidateSet(\"installed\", \"searched\")]\n        [string]$state=\"installed\",\n        [bool]$_ansible_check_mode=$false\n        )\n\n        $is_check_mode = $($state -eq \"searched\") -or $_ansible_check_mode\n\n        $category_guids = $category_names | % { MapCategoryNameToGUID $_ }\n\n        $update_status = @{ changed = $false }\n\n        Write-DebugLog \"Creating Windows Update session...\"\n        $session = New-Object -ComObject Microsoft.Update.Session\n\n        Write-DebugLog \"Create Windows Update searcher...\"\n        $searcher = $session.CreateUpdateSearcher()\n\n        # OR is only allowed at the top-level, so we have to repeat base criteria inside\n        # FUTURE: change this to client-side filtered?\n        $criteriabase = \"IsInstalled = 0\"\n        $criteria_list = $category_guids | % { \"($criteriabase AND CategoryIDs contains '$_')\" }\n\n        $criteria = [string]::Join(\" OR \", $criteria_list)\n\n        Write-DebugLog \"Search criteria: $criteria\"\n\n        Write-DebugLog \"Searching for updates to install in category IDs $category_guids...\"\n        $searchresult = $searcher.Search($criteria)\n\n        Write-DebugLog \"Creating update collection...\"\n    \n        $updates_to_install = New-Object -ComObject Microsoft.Update.UpdateColl\n\n        Write-DebugLog \"Found $($searchresult.Updates.Count) updates\"\n\n        $update_status.updates = @{ }\n\n        # FUTURE: add further filtering options\n        foreach($update in $searchresult.Updates) {\n          if(-Not $update.EulaAccepted) {\n            Write-DebugLog \"Accepting EULA for $($update.Identity.UpdateID)\"\n            $update.AcceptEula()\n          }\n\n          if($update.IsHidden) {\n            Write-DebugLog \"Skipping hidden update $($update.Title)\"\n            continue\n          }\n\n          Write-DebugLog \"Adding update $($update.Identity.UpdateID) - $($update.Title)\"\n          $res = $updates_to_install.Add($update)\n\n          $update_status.updates[$update.Identity.UpdateID] = @{\n            title = $update.Title\n            # TODO: pluck the first KB out (since most have just one)?\n            kb = $update.KBArticleIDs\n            id = $update.Identity.UpdateID\n            installed = $false\n          }\n        }\n\n        Write-DebugLog \"Calculating pre-install reboot requirement...\"\n\n        # calculate this early for check mode, and to see if we should allow updates to continue\n        $sysinfo = New-Object -ComObject Microsoft.Update.SystemInfo\n        $update_status.reboot_required = $sysinfo.RebootRequired\n        $update_status.found_update_count = $updates_to_install.Count\n        $update_status.installed_update_count = 0\n\n        # bail out here for check mode  \n        if($is_check_mode -eq $true) { \n          Write-DebugLog \"Check mode; exiting...\"\n          Write-DebugLog \"Return value: $($update_status | out-string)\"\n\n          if($updates_to_install.Count -gt 0) { $update_status.changed = $true }\n          return $update_status \n        }\n\n        if($updates_to_install.Count -gt 0) {   \n          if($update_status.reboot_required) { \n            throw \"A reboot is required before more updates can be installed.\"\n          }\n          else {\n            Write-DebugLog \"No reboot is pending...\"\n          }\n          Write-DebugLog \"Downloading updates...\" \n        }\n\n        foreach($update in $updates_to_install) {\n            if($update.IsDownloaded) { \n                Write-DebugLog \"Update $($update.Identity.UpdateID) already downloaded, skipping...\"\n                continue \n            }\n            Write-DebugLog \"Creating downloader object...\"\n            $dl = $session.CreateUpdateDownloader()\n            Write-DebugLog \"Creating download collection...\"\n            $dl.Updates = New-Object -ComObject Microsoft.Update.UpdateColl\n            Write-DebugLog \"Adding update $($update.Identity.UpdateID)\"\n            $res = $dl.Updates.Add($update)\n            Write-DebugLog \"Downloading update $($update.Identity.UpdateID)...\"\n            $download_result = $dl.Download()\n            # FUTURE: configurable download retry\n            if($download_result.ResultCode -ne 2) { # OperationResultCode orcSucceeded\n                throw \"Failed to download update $($update.Identity.UpdateID)\"\n            }\n        }\n\n        if($updates_to_install.Count -lt 1 ) { return $update_status }\n\n        Write-DebugLog \"Installing updates...\"\n\n        # install as a batch so the reboot manager will suppress intermediate reboots\n        Write-DebugLog \"Creating installer object...\"\n        $inst = $session.CreateUpdateInstaller()\n        Write-DebugLog \"Creating install collection...\"\n        $inst.Updates = New-Object -ComObject Microsoft.Update.UpdateColl\n\n        foreach($update in $updates_to_install) {\n            Write-DebugLog \"Adding update $($update.Identity.UpdateID)\"\n            $res = $inst.Updates.Add($update)\n        }\n\n        # FUTURE: use BeginInstall w/ progress reporting so we can at least log intermediate install results\n        Write-DebugLog \"Installing updates...\"\n        $install_result = $inst.Install()\n\n        $update_success_count = 0\n        $update_fail_count = 0\n\n        # WU result API requires us to index in to get the install results\n        $update_index = 0\n\n        foreach($update in $updates_to_install) {\n          $update_result = $install_result.GetUpdateResult($update_index)\n          $update_resultcode = $update_result.ResultCode\n          $update_hresult = $update_result.HResult\n\n          $update_index++\n\n          $update_dict = $update_status.updates[$update.Identity.UpdateID]\n\n          if($update_resultcode -eq 2) { # OperationResultCode orcSucceeded\n            $update_success_count++\n            $update_dict.installed = $true\n            Write-DebugLog \"Update $($update.Identity.UpdateID) succeeded\"\n          }\n          else {\n            $update_fail_count++\n            $update_dict.installed = $false\n            $update_dict.failed = $true\n            $update_dict.failure_hresult_code = $update_hresult\n            Write-DebugLog \"Update $($update.Identity.UpdateID) failed resultcode $update_hresult hresult $update_hresult\"\n          }\n\n        }\n\n        if($update_fail_count -gt 0) {  \n            $update_status.failed = $true\n            $update_status.msg=\"Failed to install one or more updates\"\n        }\n        else { $update_status.changed = $true }\n\n        Write-DebugLog \"Performing post-install reboot requirement check...\"\n\n        # recalculate reboot status after installs\n        $sysinfo = New-Object -ComObject Microsoft.Update.SystemInfo\n        $update_status.reboot_required = $sysinfo.RebootRequired\n        $update_status.installed_update_count = $update_success_count\n        $update_status.failed_update_count = $update_fail_count\n\n        Write-DebugLog \"Return value: $($update_status | out-string)\"\n\n        return $update_status\n    }\n\n    Try { \n        # job system adds a bunch of cruft to top-level dict, so we have to send a sub-dict\n        return @{ job_output = DoWindowsUpdate @boundparms }\n    }\n    Catch {\n        $excep = $_\n        Write-DebugLog \"Fatal exception: $($excep.Exception.Message) at $($excep.ScriptStackTrace)\"\n        return @{ job_output = @{ failed=$true;error=$excep.Exception.Message;location=$excep.ScriptStackTrace } }\n    }\n", "Definition": "System.Management.Automation.JobDefinition", "InstanceId": "9ba0eae9-e4d3-4e8d-8571-69dcb0c5ce7f", "Name": "ansible-win-updates", "Parameters": "System.Management.Automation.Runspaces.CommandParameterCollection"}, "JobTriggers": [], "Name": "ansible-win-updates", "Options": {"DoNotAllowDemandStart": false, "IdleDuration": "00:10:00", "IdleTimeout": "01:00:00", "JobDefinition": "Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition", "MultipleInstancePolicy": 1, "RestartOnIdleResume": false, "RunElevated": true, "RunWithoutNetwork": true, "ShowInTaskScheduler": true, "StartIfNotIdle": true, "StartIfOnBatteries": false, "StopIfGoingOffIdle": false, "StopIfGoingOnBatteries": true, "WakeToRun": false}, "PSExecutionArgs": "-NoLogo -NonInteractive -WindowStyle Hidden -Command \"Import-Module PSScheduledJob; $jobDef = [Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition]::LoadFromStore('ansible-win-updates', 'C:\\Users\\testuser\\AppData\\Local\\Microsoft\\Windows\\PowerShell\\ScheduledJobs'); $jobDef.Run()\"", "PSExecutionPath": "powershell.exe"}}, "failed": true, "msg": "An error occurred while registering scheduled job definition ansible-win-updates to the Windows Task Scheduler.  The Task Scheduler error is: Cannot create a file when that file already exists. (Exception from HRESULT: 0x800700B7)."}
        to retry, use: --limit @/home/testuser0/ansible/update_t.retry

PLAY RECAP *********************************************************************
dssw2012r2.testdomain.lan      : ok=2    changed=0    unreachable=0    failed=1   
dssdss commented 7 years ago

Also, I tried to use http://docs.ansible.com/ansible/win_scheduled_task_module.html Everything is fine with it on both windows - en and ru. Scheduled task was successfully created.

So, the problem is only with win_updates module on rus os version. As you can see, I also tried to install en_US mui on it, applied to all users and made it default system locale, but this problem still exists...

ansibot commented 7 years ago

This repository has been locked. All new issues and pull requests should be filed in https://github.com/ansible/ansible

Please read through the repomerge page in the dev guide.

dssdss commented 7 years ago

But when I went to https://github.com/ansible/ansible/issues/new I saw disclaimer:

Please do not report issues/requests related to Ansible modules here !!

Report them to the appropriate modules-core or modules-extras project:
  - https://github.com/ansible/ansible-modules-core/issues
  - https://github.com/ansible/ansible-modules-extras/issues

Also verify first that your issue/request is not already reported in GitHub

So, that's why I posted this bug there. Please, correct it!