【PowershellDSC】プロパティの未定義エラーはバージョンに注意!

こんにちは。(株)EIT2年目のMです。

今回は、2016年8月にオープンソース化したことで話題のPowershellの機能の1つ「PowershellDSC」についての記事です。

Powershell 5.0が公開されてもうすぐ1年が経とうとしていますが、皆さんはもう乗り換えましたか?Powershell 5.0ユーザがDSCを使用する場合に陥ってしまう、

プロパティ ○○ は未定義です

というエラーについてその対処法をご紹介します。

※今回の記事はPowershell4.0を使っていた方及びPowershell5.0を使っていく方向けの内容です※

PowershellDSCとは、

PowershellDSCとは、

物理ホスト、仮想マシン、オンプレミス、クラウドといったさまざまな規模のWindowsインフラ環境において、Windowsサーバー自身を「あるべき状態(Desired State)に構成(Configuration)する」ための自動化プラットフォーム

のことです。

サーバの自動構成ツールとしては「chef」「Ansible」「Puppet」「Itamae」などが普及していますが、その中でも「PowershellDSC」は

  • ・Windowsに標準搭載されている(※Windows 8.1,Windows Server 2012R2以降)
  • ・Windowsの構成管理に強い

といった特徴があります。

Powershellは進化を続ける

冒頭でも述べたようにPowershellはオープンソース化が宣言され、今後さらなる機能の追加や利便性の向上が見込まれています。

Powershell 5.0からは操作可能なWindows機能が追加されただけではなくLinuxやMacOSへ対応を始めており、今後活用の場面が増えていくと予想しています。最新の動向を知りたい場合は、公式GitHub「PowershellTeam」を見てみるといいでしょう!

プロパティの未定義エラーが発生したら・・・

さて、前置きが長くなりましたが本題に入りましょう。

今回想定する環境は管理マシンのPowershellバージョンを5.0にアップデートしたユーザが、Windows Server 2012R2などのPowershell 4.0を搭載したサーバに対してPowershellDSCを使用する場合です。

PowershellDSCユーザがPowershellのバージョンを5.0にアップデートし、従来通りにMOFファイルをプッシュした場合、こんなエラーが発生するかもしれません。(※一部”*”で伏せています)

PS C:work> Start-DscConfiguration -Wait-Verbose -Path .Hoge -CimSession $CimSession
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName'= SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName
' = root/Microsoft/Windows/DesiredStateConfiguration'.
VERBOSE: コンピューター WIN-*****、ユーザー SID *-*-*-**-*****-******-******-**** から LCM メソッドが呼び出されました。
VERBOSE: [WIN-******]: LCM:  [ 開始     設定       ]
VERBOSE: [WIN-******]: LCM:  [ 終了     設定       ]
プロパティ ConfigurationName は未定義です
 行:18、文字:2
 バッファー:
nName = "Hoge";
};^
insta
    + CategoryInfo          : SyntaxError: (root/Microsoft/...gurationManager:String) 
    [], CimException
    + FullyQualifiedErrorId : MiClientApiError_Failed
    + PSComputerName        : HogeServer
 
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 2.343 seconds

早速、エラーの原因を探ってみましょう。

使用したConfigurationを確認する

以下に示すのは、今回対象のサーバ(HogeServer)にプッシュしたConfiguration(コンフィグレーション)です。

Configuration Hoge
{
    Import-DscResource -ModuleName 'PSDesiredStateConfiguration'
    Node HogeServer
    {
        WindowsFeature FeatureAdd
        {
            Ensure = "Present"
            Name = "Web-Server"
        }
 
        Service ServiceStart
        {
            Name = "W3SVC"
            StartupType = "Manual"
            State = "Running"
        }
 
        File FilePut
        {
            Ensure = "Present"
            Type = "File"
            Contents = "<html><head><title>タイトル</title></head><body>This is PowershellDSC!</body></html>"
            DestinationPath = "C:inetpubwwwrootindex.html"
        }
    }
}

HogeServerというサーバにIISをインストールし、デフォルトページに「This is PowershellDSC!」を表示させるという非常にシンプルなConfigurationです。

特殊な操作をしているわけではない一般的なConfigurationなので、Powershell 4.0を使用していた頃は特に問題は起きていませんでした。

Configurationは問題はないため、次はMOFファイルを確認してみましょう。

Powershell 5.0で作成したMOFファイル

もう一度エラー文を確認してみましょう。

プロパティ ConfigurationName は未定義です
 行:18、文字:2

MOFファイルの18行目に原因がありそうです。18行目辺りまでを見てみます。

/*
@TargetNode='HogeServer'
@GeneratedBy=User
@GenerationDate=10/16/2016 19:30:36
@GenerationHost=User-PC
*/

instance of MSFT_RoleResource as $MSFT_RoleResource1ref
{
ResourceID = "[WindowsFeature]FeatureAdd";
 Ensure = "Present";
 SourceInfo = "::6::9::WindowsFeature";
 Name = "Web-Server";
 ModuleName = "PSDesiredStateConfiguration";

ModuleVersion = "1.0";

 ConfigurationName = "Hoge";

};
instance of MSFT_ServiceResource as $MSFT_ServiceResource1ref
{

~~~~以下略~~~~

どうやら18行目に該当する部分は

<pre class=”theme:powershell-ise lang:ps decode:true”> ConfigurationName = “Hoge”;</pre>

のようです。この部分はMOFの作成元となったConfigurationの定義名を表しています。

エラー文から考えるとMOFファイルの<strong>ConfigurationName</strong> <strong>プロパティ</strong>が定義されていないことが原因だと考えられます。つまり、

<strong>MOFの受信先となるサーバでは、このプロパティが認識できていない!</strong>

ということなんですね。

<h3>Powershell 4.0で作成したMOFファイル</h3>

プッシュ元とプッシュ先ではPowershellのバージョンが違います。この辺りに原因があるだろうということで、バージョン4.0で作成したMOFファイルを確認してみましょう。

<pre class=”lang:ps decode:true”>/*
@TargetNode=’HogeServer’
@GeneratedBy=User
@GenerationDate=9/11/2016 19:15:59
@GenerationHost=User-PC
*/

instance of MSFT_RoleResource as $MSFT_RoleResource1ref
{
ResourceID = “[WindowsFeature]FeatureAdd”;
Ensure = “Present”;
SourceInfo = “::6::9::WindowsFeature”;
Name = “Web-Server”;
ModuleName = “PSDesiredStateConfiguration”;
ModuleVersion = “1.0”;

};

instance of MSFT_ServiceResource as $MSFT_ServiceResource1ref
{

~~~~以下略~~~~

先ほど問題となった18行目に注目してみてください。ご覧のとおり、

ConfigurationNameというプロパティが存在していない!

ということが分かります。

この「ConfigurationName」というプロパティはPowershell5.0から追加された新しいプロパティだったんですね。

複数のConfigurationからMOFファイルを作成する場合に、どのConfigurationから追加されたResource(リソース)なのかを判別するためのプロパティですが、Powershell 4.0では認識できないという落とし穴なんです。

ConfigurationやMOFに文法ミスがなくてもバージョン差異によって、こんなところでエラーに苦しめられるんですね・・・

ここまでで発生したエラーの原因はある程度判明しましたが、対処の方法はあるのでしょうか。

プロパティの未定義エラーの対処方法

対処は非常に簡単です。先ほど2つのMOFファイルの中身を載せましたが基本的に異なる部分は

 ConfigurationName = "Hoge";

というプロパティのみです。このプロパティ部分を削除するとPowershell 4.0に対してDSCを使用しても問題なくプッシュすることができます。

最終的にエラーの原因となるプロパティを全て削除したMOFファイル(v5.0作)を以下に示します。

/*
@TargetNode='HogeServer'
@GeneratedBy=User
@GenerationDate=10/16/2016 19:30:36
@GenerationHost=User-PC
*/

instance of MSFT_RoleResource as $MSFT_RoleResource1ref
{
ResourceID = "[WindowsFeature]FeatureAdd";
 Ensure = "Present";
 SourceInfo = "::6::9::WindowsFeature";
 Name = "Web-Server";
 ModuleName = "PSDesiredStateConfiguration";

ModuleVersion = "1.0";


};
instance of MSFT_ServiceResource as $MSFT_ServiceResource1ref
{
ResourceID = "[Service]ServiceStart";
 State = "Running";
 SourceInfo = "::12::9::Service";
 Name = "W3SVC";
 StartupType = "Manual";
 ModuleName = "PSDesiredStateConfiguration";

ModuleVersion = "1.0";


};
instance of MSFT_FileDirectoryConfiguration as $MSFT_FileDirectoryConfiguration1ref
{
ResourceID = "[File]FilePut";
 Type = "File";
 Ensure = "Present";
 Contents = "<html><head><title>タイトル</title></head><body>This is PowershellDSC!</body></html>";
 DestinationPath = "C:inetpubwwwrootindex.html";
 ModuleName = "PSDesiredStateConfiguration";
 SourceInfo = "::19::9::File";

ModuleVersion = "1.0";


};
instance of OMI_ConfigurationDocument


                    {
 Version="2.0.0";

                        Author="User";
 
                        GenerationDate="10/16/2016 19:30:36";
 
                        GenerationHost="User-PC";
 
                    };

エラー文に沿って、未定義と警告される部分を削除していくことで上記のMOFファイルが完成します。

では、このMOFファイルをプッシュしてみましょう。

無事にプッシュ成功!

実際にプッシュした結果がこちらです。

PS C:work> Start-DscConfiguration -Wait -Verbose -Path .Hoge -CimSession $SimSession
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName ' = root/Microsoft/Windows/DesiredStateConfiguration'.
VERBOSE: コンピューター WIN-*******、ユーザー SID *-*-*-*-******-*****-*******-*** から LCM メソッドが呼び出されました。
VERBOSE: [WIN-*******]: LCM:  [ 開始     設定       ]
VERBOSE: [WIN-*******]: LCM:  [ 開始     リソース     ]  [[WindowsFeature]FeatureAdd]
VERBOSE: [WIN-*******]: LCM:  [ 開始     テスト      ]  [[WindowsFeature]FeatureAdd]
VERBOSE: [WIN-*******]:                            [[WindowsFeature]FeatureAdd] 操作 'Get-WindowsFeature' が開始されました: Web-Server
VERBOSE: [WIN-*******]:                            [[WindowsFeature]FeatureAdd] 操作 'Get-WindowsFeature' は成功しました: Web-Server
VERBOSE: [WIN-*******]: LCM:  [ 終了     テスト      ]  [[WindowsFeature]FeatureAdd]  51.7820 秒かかりました。
VERBOSE: [WIN-*******]: LCM:  [ 開始     設定       ]  [[WindowsFeature]FeatureAdd]
VERBOSE: [WIN-*******]:                            [[WindowsFeature]FeatureAdd] インストールを開始しました...
VERBOSE: [WIN-*******]:                            [[WindowsFeature]FeatureAdd] 前提条件の処理が開始されました...
VERBOSE: [WIN-*******]:                            [[WindowsFeature]FeatureAdd] 前提条件の処理が正常に完了しました。
WARNING: [WIN-*******]:                            [[WindowsFeature]FeatureAdd] Windows 自動更新が有効になっていません。新しくインストールした役割または機能が自動的に更新されるようにするには、[Windows Update] を有効にしてください。
VERBOSE: [WIN-*******]:                            [[WindowsFeature]FeatureAdd] インストールが正常に完了しました。
VERBOSE: [WIN-*******]:                            [[WindowsFeature]FeatureAdd] successfully installed the feature Web-Server
VERBOSE: [WIN-*******]: LCM:  [ 終了     設定       ]  [[WindowsFeature]FeatureAdd]  143.2100 秒かかりました。
VERBOSE: [WIN-*******]: LCM:  [ 終了     リソース     ]  [[WindowsFeature]FeatureAdd]
VERBOSE: [WIN-*******]: LCM:  [ 開始     リソース     ]  [[Service]ServiceStart]
VERBOSE: [WIN-*******]: LCM:  [ 開始     テスト      ]  [[Service]ServiceStart]
VERBOSE: [WIN-*******]:                            [[Service]ServiceStart] サービス 'W3SVC' の開始の種類は 'Auto' です。'Manual' と一致しません。
VERBOSE: [WIN-*******]: LCM:  [ 終了     テスト      ]  [[Service]ServiceStart]  1.1880 秒かかりました。
VERBOSE: [WIN-*******]: LCM:  [ 開始     設定       ]  [[Service]ServiceStart]
VERBOSE: [WIN-*******]:                            [[Service]ServiceStart] サービス 'W3SVC' は既に開始されています。操作は必要ありません。
VERBOSE: [WIN-*******]: LCM:  [ 終了     設定       ]  [[Service]ServiceStart]  1.0160 秒かかりました。
VERBOSE: [WIN-*******]: LCM:  [ 終了     リソース     ]  [[Service]ServiceStart]
VERBOSE: [WIN-*******]: LCM:  [ 開始     リソース     ]  [[File]FilePut]
VERBOSE: [WIN-*******]: LCM:  [ 開始     テスト      ]  [[File]FilePut]
VERBOSE: [WIN-*******]:                            [[File]FilePut] 宛先オブジェクトが見つかったため、何もする必要はありません。
VERBOSE: [WIN-*******]: LCM:  [ 終了     テスト      ]  [[File]FilePut]  0.4680 秒かかりました。
VERBOSE: [WIN-*******]: LCM:  [ スキップ   設定       ]  [[File]FilePut]
VERBOSE: [WIN-*******]: LCM:  [ 終了     リソース     ]  [[File]FilePut]
VERBOSE: [WIN-*******]: LCM:  [ 終了     設定       ]
VERBOSE: [WIN-*******]: LCM:  [ 終了     設定       ]    (221.1170 秒)。
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 223.029 seconds

Operation ‘Invoke CimMethod’ complete.」ということで無事に成功していることがわかります。

Windows 自動更新に関するWARNINGが表示されていますがサーバで有効にしていないだけですので、これは特に問題ありません。

まとめ

今回のようにPowershellDSCにおいて「バージョン差異に起因するプロパティの未定義エラー」が発生した場合は、該当箇所を削除することで解決できます。

また今回のようなバージョン差異による落とし穴に陥らないためには、プッシュ先サーバのPowershellバージョン合わせてMOFを作成することが望ましいでしょう。

PowershellDSCは他の構成管理ツールに比べると歴史が浅く情報も少ないため、エラーが起きてしまった場合は対処に困るかもしれません。そんな時はエラー内容をよく確認し、可能性のある要因を1つ1つ解消していきましょう。

またコミュニティによって公開されているリソースを使用することで、想定外のエラーを未然に防ぐことも大切です。

これから更に発展していく可能性のある分野ですので、是非皆さんも挑戦してみてください!