使用 MOF 编写自定义 DSC 资源

适用于:Windows PowerShell 4.0、Windows PowerShell 5.0

在本文中,我们将在 MOF 文件中定义 Windows PowerShell 所需状态配置 (DSC) 自定义资源的架构,并在 Windows PowerShell 脚本文件中实现该资源。 此自定义资源用于创建和维护网站。

创建 MOF 架构

架构定义了可由 DSC 配置脚本配置的资源属性。

MOF 资源的文件夹结构

若要使用 MOF 架构实现 DSC 自定义资源,请创建以下文件夹结构。 MOF 架构在文件 Demo_IISWebsite.schema.mof中定义,资源脚本在 中定义 Demo_IISWebsite.psm1。 (可选)可以创建模块清单 (psd1) 文件。

$env:ProgramFiles\WindowsPowerShell\Modules (folder)
    |- MyDscResources (folder)
        |- MyDscResources.psd1 (file, required)
        |- DSCResources (folder)
            |- Demo_IISWebsite (folder)
                |- Demo_IISWebsite.psd1 (file, optional)
                |- Demo_IISWebsite.psm1 (file, required)
                |- Demo_IISWebsite.schema.mof (file, required)

注释

必须在顶级文件夹下创建一个名为 DSCResources 的文件夹,并且每个资源的文件夹必须与资源具有相同的名称。

MOF 文件的内容

下面是可用于自定义网站资源的 MOF 文件示例。 要遵循此示例,请将此架构保存到文件中,然后调用文件 Demo_IISWebsite.schema.mof

[ClassVersion("1.0.0"), FriendlyName("Website")]
class Demo_IISWebsite : OMI_BaseResource
{
  [Key] string Name;
  [Required] string PhysicalPath;
  [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure;
  [write,ValueMap{"Started","Stopped"},Values{"Started", "Stopped"}] string State;
  [write] string Protocol[];
  [write] string BindingInfo[];
  [write] string ApplicationPool;
  [read] string ID;
};

请注意前面代码的以下几点:

  • FriendlyName 定义可用于在 DSC 配置脚本中引用此自定义资源的名称。 在此示例中, Website 等效于内置存档资源的友好名称 Archive
  • 您为自定义资源定义的类必须派生自 OMI_BaseResource
  • 属性上的类型限定符 [Key]指示此属性将唯一标识资源实例。 至少需要一个 [Key] 属性。
  • [Required]限定符指示该属性是必需的(必须在使用此资源的任何配置脚本中指定值)。
  • [write]限定符指示在配置脚本中使用自定义资源时,此属性是可选的。 限定 [read] 符表示配置无法设置属性,并且仅用于报告目的。
  • Values 将可分配给属性的值限制为 中定义 ValueMap的值列表。 有关详细信息,请参阅 ValueMap 和值限定符
  • 建议在资源中包含一个调用 Ensure with values PresentAbsent 的属性,以维护内置 DSC 资源的样式一致。
  • 将自定义资源的架构文件命名如下: classname.schema.mof,其中 classname 是架构定义中关键字后面 class 的标识符。

编写资源脚本

资源脚本实现资源的逻辑。 在本模块中,您必须包含三个名为 Get-TargetResourceSet-TargetResourceTest-TargetResource的函数。 所有三个函数都必须采用与为资源创建的 MOF 架构中定义的属性集相同的参数集。 在本文档中,这组属性称为“资源属性”。将这三个函数存储在名为 <ResourceName>.psm1的文件中。 在以下示例中,函数存储在名为 Demo_IISWebsite.psm1的文件中。

注释

在资源上多次运行同一配置脚本时,不应收到任何错误,并且资源应保持与运行一次脚本相同的状态。 为此,请确保 your Get-TargetResourceTest-TargetResource 函数保持资源不变,并且在具有相同参数值的序列中多次调用该 Set-TargetResource 函数始终等同于调用一次。

在函数实现中 Get-TargetResource ,使用作为参数提供的关键资源属性值来检查指定资源实例的状态。 此函数必须返回一个哈希表,该哈希表将所有资源属性列为键,并将这些属性的实际值列为相应的值。 以下代码提供了一个示例。

# DSC uses the Get-TargetResource function to fetch the status of the resource instance
# specified in the parameters for the target machine
function Get-TargetResource
{
    param
    (
        [ValidateSet("Present", "Absent")]
        [string]$Ensure = "Present",

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$PhysicalPath,

        [ValidateSet("Started", "Stopped")]
        [string]$State = "Started",

        [string]$ApplicationPool,

        [string[]]$BindingInfo,

        [string[]]$Protocol
    )

        $getTargetResourceResult = $null;

        <#
          Insert logic that uses the mandatory parameter values to get the website and
          assign it to a variable called $Website
          Set $ensureResult to "Present" if the requested website exists and to "Absent" otherwise
        #>

        # Add all Website properties to the hash table
        # This simple example assumes that $Website is not null
        $getTargetResourceResult = @{
            Name = $Website.Name
            Ensure = $ensureResult
            PhysicalPath = $Website.physicalPath
            State = $Website.state
            ID = $Website.id
            ApplicationPool = $Website.applicationPool
            Protocol = $Website.bindings.Collection.protocol
            Binding = $Website.bindings.Collection.bindingInformation
        }

        $getTargetResourceResult
}

根据为配置脚本中的资源属性指定的值,必须 Set-TargetResource 执行下列作之一:

  • 创建新网站
  • 更新现有网站
  • 删除现有网站

下面的示例对此进行了演示。

# The Set-TargetResource function is used to create, delete or configure a website on the target machine.
function Set-TargetResource
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    param
    (
        [ValidateSet("Present", "Absent")]
        [string]$Ensure = "Present",

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$PhysicalPath,

        [ValidateSet("Started", "Stopped")]
        [string]$State = "Started",

        [string]$ApplicationPool,

        [string[]]$BindingInfo,

        [string[]]$Protocol
    )

    <#
        If Ensure is set to "Present" and the website specified in the mandatory input parameters
          does not exist, then create it using the specified parameter values
        Else, if Ensure is set to "Present" and the website does exist, then update its properties
          to match the values provided in the non-mandatory parameter values
        Else, if Ensure is set to "Absent" and the website does not exist, then do nothing
        Else, if Ensure is set to "Absent" and the website does exist, then delete the website
    #>
}

最后,该Test-TargetResource函数必须采用与 和 Set-TargetResource相同的Get-TargetResource参数集。 在 的 Test-TargetResource实现中,检查键参数中指定的资源实例的状态。 如果资源实例的实际状态与参数集中指定的值不匹配,则返回 $false。 否则,返回 $true.

以下代码实现了该 Test-TargetResource 函数。

function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [ValidateSet("Present","Absent")]
        [System.String]
        $Ensure,

        [parameter(Mandatory = $true)]
        [System.String]
        $Name,

        [parameter(Mandatory = $true)]
        [System.String]
        $PhysicalPath,

        [ValidateSet("Started","Stopped")]
        [System.String]
        $State,

        [System.String[]]
        $Protocol,

        [System.String[]]
        $BindingData,

        [System.String]
        $ApplicationPool
    )

    # Get the current state
    $currentState = Get-TargetResource -Ensure $Ensure -Name $Name -PhysicalPath $PhysicalPath -State $State -ApplicationPool $ApplicationPool -BindingInfo $BindingInfo -Protocol $Protocol

    # Write-Verbose "Use this cmdlet to deliver information about command processing."

    # Write-Debug "Use this cmdlet to write debug information while troubleshooting."

    # Include logic to
    $result = [System.Boolean]
    # Add logic to test whether the website is present and its status matches the supplied
    # parameter values. If it does, return true. If it does not, return false.
    $result
}

注释

为了更轻松地调试,请在 Write-Verbose 前三个函数的实现中使用 cmdlet。 此 cmdlet 将文本写入详细消息流。 默认情况下,不显示详细消息流,但可以通过更改 $VerbosePreference 变量的值或使用 DSC cmdlet = new 中的 详细 参数来显示它。

创建模块清单

最后,使用 cmdlet 为 New-ModuleManifest 自定义资源模块定义文件 <ResourceName>.psd1 。 调用此 cmdlet 时,请引用上一节中所述的脚本模块 (.psm1) 文件。 在要导出的函数列表中包括 Get-TargetResourceSet-TargetResource和 。Test-TargetResource 下面是一个示例清单文件。

# Module manifest for module 'Demo.IIS.Website'
#
# Generated on: 1/10/2013
#

@{

# Script module or binary module file associated with this manifest.
# RootModule = ''

# Version number of this module.
ModuleVersion = '1.0'

# ID used to uniquely identify this module
GUID = '6AB5ED33-E923-41d8-A3A4-5ADDA2B301DE'

# Author of this module
Author = 'Contoso'

# Company or vendor of this module
CompanyName = 'Contoso'

# Copyright statement for this module
Copyright = 'Contoso. All rights reserved.'

# Description of the functionality provided by this module
Description = 'This Module is used to support the creation and configuration of IIS Websites through Get, Set and Test API on the DSC managed nodes.'

# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '4.0'

# Minimum version of the common language runtime (CLR) required by this module
CLRVersion = '4.0'

# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @("WebAdministration")

# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
NestedModules = @("Demo_IISWebsite.psm1")

# Functions to export from this module
FunctionsToExport = @("Get-TargetResource", "Set-TargetResource", "Test-TargetResource")

# Cmdlets to export from this module
#CmdletsToExport = '*'

# HelpInfo URI of this module
# HelpInfoURI = ''
}

支持 PsDscRunAsCredential

注释

PowerShell 5.0 及更高版本支持 PsDscRunAsCredential

PsDscRunAsCredential 属性可用于 DSC 配置资源块,以指定资源应在一组指定的凭据下运行。 有关详细信息,请参阅 使用用户凭据运行 DSC

要从自定义资源中访问用户上下文,可以使用 自动变量 $PsDscContext

例如,以下代码会将运行资源的用户上下文写入详细输出流:

if (PsDscContext.RunAsUser) {
    Write-Verbose "User: $PsDscContext.RunAsUser";
}

重新启动节点

如果函数 Set-TargetResource 中执行的作需要重新启动,则可以使用全局标志告诉 LCM 重新启动节点。 此重新启动会在功能完成后 Set-TargetResource 直接发生。

在函数中 Set-TargetResource ,添加以下代码行。

# Include this line if the resource requires a system reboot.
$global:DSCMachineStatus = 1

为了使 LCM 重新启动节点,需要将 RebootNodeIfNeeded 标志设置为 $trueActionAfterReboot 设置还应设置为 ContinueConfiguration,这是默认设置。 有关配置 LCM 的详细信息,请参阅配置本地配置管理器配置本地配置管理器 (v4)。