Ansibleで英語版WindowsOSを日本語化してSQLServerをインストールする

# はじめに
Ansibleを使って、英語版WindowsServer2016のComputeEngineImageを日本語化して、SQLServerExpressをインストールするのに盛大にハマった。。。
そして、ググっても同じことでハマってる記事が見つからず、どこかの誰かの役に立てればと思った。

Ansibleから対象VMに接続するところまではどこにでも載ってるし割愛。


## Ansible環境
* CentOS 7
* Ansible 2.6.1

## インストール先のVM
* WindowsServer2016

## WindowsServerの日本語化

### windows firewallのオフ
これは[公式ドキュメント](https://docs.ansible.com/ansible/2.6/modules/win_firewall_module.html#win-firewall-module)とほとんど同じまま

```yaml
- name: Enable firewall for Domain, Public and Private profiles
  win_firewall:
    state: disabled
    profiles:
    - Private
    - Public
  tags: disable_firewall
```

### 言語パックのインストール
言語パックが入っていなかったらインストールし、再起動。
※言語パックはCloudStorageにアップロード済み

```yaml
- name: create temp directory
  win_file:
    path: C:\temp
    state: directory
- name: download language pack
  win_shell: gsutil cp "{{ language_pack }}" c:\temp\
- name: install language pack
  win_shell: |
    $LangPacks = DISM.exe /Online /Get-Intl /English |
    Select-String -SimpleMatch 'Installed language(s)'|
        ForEach-Object {
            if($_ -match ':\s*(.*)'){$Matches[1]}
        }

    if($LangPacks -notcontains 'ja-JP'){
      Dism /online /Add-Package /PackagePath:c:\temp\lp.cab
    }

- name: reboot
  win_reboot:
```

### タイムゾーンやロケールの設定
タイムゾーンやロケールやUIを日本に設定する

```yaml
- name: Set timezone to 'Japan' 
  win_timezone:
    timezone: Tokyo Standard Time

- name: Region設定
  win_region:
    copy_settings: "true"
    location: "122"
    format: ja-JP
    unicode_language: ja-JP
  register: result

- name: 日本語UIの明示
  win_shell: Set-WinUILanguageOverride -Language ja-JP

- name: 日付・時刻の[形式]を表示言語と同一にする
  win_shell: Set-WinCultureFromLanguageListOptOut -OptOut $False

- name: setLanguagelist
  win_shell: Set-WinUserLanguageList -LanguageList ja-JP,en-US -Force

- name: キーボード設定を日本語化
  win_shell: Set-ItemProperty 'registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters' -Name 'LayerDriver JPN' -Value 'kbd106.dll'

- name: 既定の入力方式を上書き
  win_shell: Set-WinDefaultInputMethodOverride -InputTip "0411:00000411"

- name: Change Region - Reboot
  win_reboot: 
  when: result.restart_required
```

### .Net frameworkのインストール

```yaml
- name: Install NET-Framework-Core from file
  win_feature:
    name: NET-Framework-Core
    state: present
```

### ようこそ画面と新しいユーザーアカウントの設定
これを設定していなかったために、超ハマった。
GUIでこれを設定する(PowerShellとかでやる方法が見つから無かった。。。)

<img width="464" alt="ようこそ画面と新しいユーザーアカウントの設定.png" src="https://qiita-image-store.s3.amazonaws.com/0/33101/d639153a-58b7-0c5d-6ae3-0bcd9984129f.png">


### SQLServerのインストール

```yaml
- name: create installer directory
  win_file:
    path: C:\temp\sqlserver_installer
    state: directory

- name: download SQLServer installer
  win_shell: gsutil cp -r "{{ sqlserver_installer }}" C:\temp\sqlserver_installer\

- name: download PsExec
  win_shell: gsutil cp -r "{{ PsExec_installer }}" c:\temp\

- name: SQLServerインストール
  win_psexec:
#コマンドは適宜要変更
    command: C:\temp\sqlserver_installer\setup.exe /Q /CONFIGURATIONFILE=C:\temp\sqlserver2008R2\ConfigurationFile.ini" /IAcceptSQLServerLicenseTerms="True"
    priority: high
    executable: C:\temp\PSTools\PsExec64.exe
    username: "{{ ansible_user }}"
    password: "{{ ansible_password }}"
    system: yes
```

### おまけ：エラーが出たときのログ
こんな感じに英語と認識されていた。

```
  OS region:                     United States
  OS language:                   English (United States)
```

```
Exception summary:
The following is an exception stack listing the exceptions in outermost to innermost order
Inner exceptions are being indented

Exception type: Microsoft.SqlServer.Configuration.RulesEngineExtension.RulesEngineRuleFailureException
    Message: 
        The language of the original SQL Server 2008 R2 media and the language of the service pack do not match. To continue, match the language of the service pack with the original SQL Server 2008 R2 media.
    Data: 
      SQL.Setup.FailureCategory = RuleViolationFailure
      DisableWatson = true
    Stack: 
        at Microsoft.SqlServer.Configuration.RulesEngineExtension.RunRulesAction.ExecuteAction(String actionId)
        at Microsoft.SqlServer.Chainer.Infrastructure.Action.Execute(String actionId, TextWriter errorStream)
        at Microsoft.SqlServer.Setup.Chainer.Workflow.ActionInvocation.ExecuteActionHelper(TextWriter statusStream, ISequencedAction actionToRun)
```