You are an expert in PowerShell DSC (or maybe not an expert, just someone playing around with configurations in DSC) and have already written fairly large and complex configurations for configuring your environment/data center. Everything is working well and you are a great fan of DSC. There’s only one problem: your work is complicated. Before long, you have a configuration that is hundreds or thousands of lines long – people from many different teams are editing it. Finding and fixing problems becomes nearly impossible… your configuration is just too unwieldy. Then comes a day when there arises a need to add something more (or maybe delete something) to your configuration. The problem looks trivial to solve right? –Just add one more resource to your (already big) configuration. But you are a forward thinking person and find yourself wondering if there is something clever you can do leverage your existing configuration scripts.
That is why we made configurations composable and reusableJ. Yes, one configuration can call another. How? That is what we are going to cover in this post.
The way to make a configuration reusable is by making it what we call a composite resource. Let me walk you through an example to do just that.
I have the following parameterized configuration (the parameters of the configuration become the properties of the composite resource) which I will turn into a composite resource:
ConfigurationxVirtualMachine
{
param
(
# Name of VMs
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String[]]$VMName,
# Name of Switch to create
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String]$SwitchName,
# Type of Switch to create
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String]$SwitchType,
# Source Path for VHD
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String]$VhdParentPath,
# Destination path for diff VHD
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String]$VHDPath,
# Startup Memory for VM
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String]$VMStartupMemory,
# State of the VM
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String]$VMState
)
# Import the module that defines custom resources
Import-DscResource-ModulexComputerManagement,xHyper-V
# Install the HyperV role
WindowsFeatureHyperV
{
Ensure="Present"
Name="Hyper-V"
}
# Create the virtual switch
xVMSwitch$switchName
{
Ensure="Present"
Name=$switchName
Type=$SwitchType
DependsOn="[WindowsFeature]HyperV"
}
# Check for Parent VHD file
FileParentVHDFile
{
Ensure="Present"
DestinationPath=$VhdParentPath
Type="File"
DependsOn="[WindowsFeature]HyperV"
}
# Check the destination VHD folder
FileVHDFolder
{
Ensure="Present"
DestinationPath=$VHDPath
Type="Directory"
DependsOn="[File]ParentVHDFile"
}
# Creae VM specific diff VHD
foreach($Namein$VMName)
{
xVHD"VhD$Name"
{
Ensure="Present"
Name=$Name
Path=$VhDPath
ParentPath=$VhdParentPath
DependsOn= @("[WindowsFeature]HyperV",
"[File]VHDFolder")
}
}
# Create VM using the above VHD
foreach($Namein$VMName)
{
xVMHyperV"VMachine$Name"
{
Ensure="Present"
Name=$Name
VhDPath= (Join-Path-Path$VhDPath-ChildPath$Name)
SwitchName=$SwitchName
StartupMemory=$VMStartupMemory
State=$VMState
MACAddress=$MACAddress
WaitForIP=$true
DependsOn= @("[WindowsFeature]HyperV",
"[xVHD]Vhd$Name")
}
}
}
The key is to place the configuration in a file with the extension schema.psm1. You can take a look here to find out how to deploy a DSC Resource. Here is how it looks on my machine:
PS C:\Program Files\WindowsPowerShell\Modules\TestCompositeResource\DSCResources\xVirtualMachine> dir
Directory: C:\Program Files\WindowsPowerShell\Modules\TestCompositeResource\DSCResources\xVirtualMachine
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2/25/2014 8:42 PM 2642 xVirtualMachine.psd1
-a--- 2/25/2014 8:42 PM 2957 xVirtualMachine.schema.psm1
Note: Take note of the .psd1 file (xVirtualMachine.psd1) inside the DSCResources folder. On my first attempt, I did not put that file in there and wasted some time trying to figure out where I was going wrong (yes, yes, yes a valid PowerShell module must have one out of .psd1, .psm1, .cdxml, .dll extension and it took me some time to figure out the fact that .schema.psm1 does not satisfy that condition).
Inside the .psd1 file, I have this line:
RootModule ='xVirtualMachine.schema.psm1'
That is it, you are done!
PS C:\> Get-DscResource -Name xVirtualMachine
ImplementedAs Name Module Properties
------------- ---- ------ ----------
Composite xVirtualMachine TestCompositeResource {VMName, SwitchName, SwitchType, VhdParentPath...}
Your configuration shows up as a composite resource.
Let us now see how to use it:
configurationRenameVM
{
Import-DscResource-ModuleTestCompositeResource
Node localhost
{
xVirtualMachine VM
{
VMName ="Test"
SwitchName ="Internal"
SwitchType ="Internal"
VhdParentPath ="C:\Demo\Vhd\RTM.vhd"
VHDPath ="C:\Demo\Vhd"
VMStartupMemory =1024MB
VMState ="Running"
}
}
Node "192.168.10.1"
{
xComputerName
{
Name="SQL01"
DomainName="fourthcoffee.com"
}
}
}
We have used the dynamic keyword Import-DscResource to make our composite resource type available in the configuration. The parameters of the composite resource become its properties. You can discover this in two ways, one way is to use the Get-DscResource cmdlet as above and the other is in ISE. I like the one in ISE since it does not require me to shift my focus to the command window and type in the cmdlet. You can take the cursor to the place where you have the name of the resource, and press CTRL+space. You can discover all the resources by using CTRL+Space after the configuration keyword as well. .You have to do it after Import-DscResource if importing custom resources.
Here is what ISE displays:
Tab completion works on the names of the properties just like any other resource, isn’t that cool?
This way, I have a configuration, where I reused one of my existing configurations and added one more resource to the overall configuration of my machine. This configuration first creates a VM and then uses the xComputerResource to rename it. I can thus build upon my existing configurations as and when the need arises for more complex configurations.
Happy configuring!
Abhik Chatterjee
Windows PowerShell Developer