A Windows PowerShell Desired State Configuration (DSC) resource contains a module file (*.psm1), an optional data file (*.psd1),and a *.schema.mof file. Details about what each of those files should look like, and how you can create those files using a DSC Resource Designer Tool, are discussed in an earlier blog post. In this blog post, we will explore the following.
- How to deploy DSC resources to the local computer
- How to discover the resources deployed, while authoring a new configuration
- How to deploy resources to the pull server, and how the local configuration manager (LCM) locates the required resources on the pull server.
Deploying DSC resources to the local computer
All DSC resources should be deployed in the following folder hierarchy:-
$env: psmodulepath (folder)
|- <ModuleName> (folder)
|- DSC Resources (folder)
|- <DSCResourceName1> (folder)
|- <DSCResourceName1.psd1> (file, optional)
|- <DSCResourceName1.psm1> (file, required)
|- <DSCResourceName1.schema.mof> (file, required)
|- <DSCResourceName2>(folder)
|- <DSCResourceName2.psd1> (file, optional)
|- <DSCResourceName2.psm1> (file, required)
|- <DSCResourceName2.schema.mof> (file, required)
Example: Suppose the Hyper-V team decided to add a resource named VM in to their existing PowerShell module under $pshome, Then the folder structure of their DSC resource would look like the following.
C:\Windows\system32\WindowsPowerShell\v1.0\Modules\Hyper-V\DSCResourcs\VM\ -VM.psd1(optional) -VM.psm1 -VM.Schema.mof
Usually, the environment variable $env:psmodulePath contains more than one path, and you can deploy DSC resources in any one of the paths. But there are some subtle differences during authoring or applying configuration to the system. Because LCM runs in System context, applying a configuration fails if your resources module are not in the $pshome or $env:ProgramFiles folder. The differences in the authoring experience are discussed in this post, in the Import-DSCResources section.
How to use and discover DSC resources
The number of PowerShell modules and cmdlets are increasing in every PowerShell release, hence increasing the number of results returned by Get-Module and Get-Command. To keep those cmdlets useful, DSC resources have been stored in a subfolder of a main PowerShell module folder.
Because DSC Resources are not deployed directly under $env: psmodulepath, they cannot be discovered by running the Get-Module -List Available cmdlet. Get-Command for the GET/SET/TEST method of the resources will fail. Also, you can’t import the DSC resource with a partial name, as shown in the following examples.
Let us try to find MSFT_EnvironmentResource, one of the DSC resources which is shipped with PowerShell 4.0.
Get-ModuleMSFT_EnvironmentResource–ListAvailable # empty (not found)
Get-CommandGET # Error: Command not found exception.
Import-ModuleMSFT_EnvironmentResource# Error: ModuleNotFound
You can, however, import the module by using its full path, like any PowerShell module, and call its GET/SET/TEST methods.
Import-ModuleC:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\DSCResources\MSFT_EnvironmentResource # Works
There are two new cmdlets that are added in PowerShell 4.0 to help discover DSC resources.
Get-DscResource: Gets all the DSC resources. You can pass a resource name list to filter the result.
Example:-Get-DscResource Env*ment, Windows*, Log ß Returns all the resources that match the specified criteria.
So one way to test if your resources are deployed correctly is to see if they are being discovered by Get-DscResource.
Import-DscResource: Import-DScResource is a dynamic keyword which can only be used inside a Configuration script block. When you are authoring a new configuration, you must import the resources needed by your configuration using this cmdlet. But if your DSC resources are stored in $pshome, you don’t need to explicitly import them. They are automatically loaded by PowerShell.
The signature of the cmdlet is shown below.
Import-DscResource [-Name <ResourceName(s)>] [-ModuleName <ModuleName(s)>]
Name: This is the DSC resource name(s) that you must import. If the module name is specified, the command searches for these DSC resources within this module; otherwise the command searches the DSC resources in all DSC resource paths.
ModuleName: This is the container module name(s), or module specification(s). If the DSC resources that are required are specified, the command will try to import only those resources from the module(s).; Otherwise, the command imports all the DSC resources in this module.
You can specify either one or both Name and ModuleName parameters in the cmdlet. But you must explicitly pass pairs of the parameter name and its value. Positional parameters are not supported.
Import-DscResource is a second way to make sure your resources are deployed correctly.
Example:-
Configuration MSDSCConfiguration {
Import-DSCResource-ModuleNameMS_DSC1, MS_DSC2-nameResource1, Resource2, Resource3
# Search for and imports Resource1 Resource2, and Resource3 inside the modules MS_DSC1,MS_DSC2
Import-DSCResource -NameResource1
# Search DSC resources for Resource1 under all valid DSC resource paths, and import the
# resource. Note that this will run slower because it has to search the resource in all the
# valid DSC resource folders.
Import-DSCResource-ModuleNameMS_DSC1
# Search for and import all DSC resources inside the module MS_DSC1.
...
}
Deploying DSC resources to the pull server
After you configure your pull server [For details about how to configure a pull server, and how a pull client works, see this blog post]. DSC resources can be packaged and placed in the pull server resource repository for pull clients to download it. The folder hierarchy of the pull server DSC Resource repository should be the following.
$env:ProgramFiles\WindowsPowerShell\DscService\Modules\ (folder) ModuleName_Version.zip ModuleName_Version.zip.checksum
When it’s unzipped, ModuleName_Version.zip should have the same folder structure as the local computer deployment hierarchy shown at the beginning of this blog post.
- The Version is the version of the module, not the version of the DSC resource. Versioning works at the module level, not the DSC resource level.
- ModuleName_Version.zip. Checksum is a checksum of the zip file generated by running the following command.
New-DSCCheckSum –path $env:ProgramFiles\WindowsPowerShell\DscService\Modules\ -force
A configuration stored in the pull server configuration repository that requires the preceding module must refer to the module as follows.
instance of <ResourceName>
{
….
ModuleName = "<ModuleName>";
ModuleVersion =“<Version>";
};
After LCM downloads a configuration from the pull server, it checks if the resources needed by the configuration exists on the local machine. If it does not exist, LCM queries the Download Manager of the local machine to download the required module, by specifying the ModuleName and ModuleVersion. After the module is downloaded and verified, it is saved to the $env: ProgramFiles\WindowsPowershell\Modules\ folder, and the configuration is applied by calling the TEST and SET methods of each resources.
Berhe Abrha
PowerShell Team