PowerCLI DSC Resource for Snapshot check.
Finally after a week of exploring DSC and building custom resource modules, i was finally able to build a custom DSC resource using PowerCLI.
Huge Thanks to my friend Ravi, MVP PowerShell for helping me out with my queries.You can see nice DSC and powershell posts from him at http://www.powershellmagazine.com
The PowerCLI DSC Resource which i created check’s for configurations of snapshots on a set of vm’s in a resource pool, and based on the condition “Ensure = Present” / “Ensure = Absent” takes the appropriate actions of creating snapshots on the VM’s / removing all the existing snapshots.
I built this resource to share how we can integrate DSC with PowerCLI to build powerful tools for configuration management, this resource can be effectively used to remove snapshots on VM’s if they are left to exist and also admins tend to forget after the VI infrastructure change activities.
Next let me go through a step by step process of how i built this resource using powercli, although resources can be also built using C# etc, i wanted to show how an IT pro can also start building his own resources.
So let me start with the first step of building your resources and that is to make yourself a Resource Schema MOF file.
In an ISE editor or even a notepad, type in the below and create the MOF Files. The class consists of the properties which need to be passed as parameters to the resources. i my DSC resource i have the vcentername, the resourcepool name and also the DomainAdmin credentials to connect to the vcenter.
[ClassVersion("1.0"), FriendlyName("PowerCLISnapShotCheck")] class DSC_PowerCLISnapShotCheck : OMI_BaseResource { [Key] string vcentername; [Key] string resourcepoolname; [Write, EmbeddedInstance("MSFT_Credential")] String DomainAdministratorCredential; [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; };
Once you create the schema mof file, save it as “DSC_PowerCLISnapShotCheck.schema.mof”.
Next lets move on to the actual PowerShell module which does all the heavy lifting, to create a DSC resource we need to have 3 set of functions which are the “Get-TargetResource”, “Set-TargetResource” and “Test-TargetResource”.
When ever a DSC configuration is invoked, the Test-TargetResource tests the system as per the configuration specified by the user, based on the conditions specified it calls the Set-TargetResource to take an appropriate action. This was in short , For more details on these please refer to a nice article at PowerShell.org
So here is the actual function which has the logic build in and does all the “Make It Happen” :).
function Test-TargetResource { [OutputType([boolean])] param ( [parameter(Mandatory)] [string] $vcentername, [parameter(Mandatory)] [string] $resourcepoolname, [Parameter(Mandatory)] [PSCredential]$DomainAdministratorCredential, [ValidateSet('Present','Absent')] [string] $Ensure = 'Present' ) try { #Addpssnapin VMware.VimAutomation.Core Add-PSSnapin VMware.VimAutomation.Core Write-Verbose "Connecting to vCenter $vcentername with credentials $credentialfile" Connect-VIServer -server $vcentername -Credential $DomainAdministratorCredential | Out-Null Write-Verbose "Checking if the snapshots exist or doesnot exist" $snapshotExist = Get-ResourcePool $resourcepoolname | Get-VM | Get-Snapshot if ($Ensure -eq "Present") { if ($snapshotExist) { Write-Verbose "Snapshots Exists for these set of VM's. No need of taking further action" return $true } else { Write-Verbose "Snapshots don't exists for these set of VM's in $resourcepoolname" return $false } } else { if ($snapshotExist) { Write-Verbose "Snapshots exist on these VM's; snapshots must be removed." return $false } else { Write-Verbose "Snapshots does not exist; nothing to remove." return $true } } } catch { $exception = $_ Write-Verbose "Error occurred while executing Test-TargetResource function" while ($exception.InnerException -ne $null) { $exception = $exception.InnerException Write-Verbose $exception.message } } return $false } function Set-TargetResource { param ( [parameter(Mandatory)] [string] $vcentername, [parameter(Mandatory)] [string] $resourcepoolname, [Parameter(Mandatory)] [PSCredential]$DomainAdministratorCredential, [ValidateSet('Present','Absent')] [string] $Ensure = 'Present' ) try { #Addpssnapin VMware.VimAutomation.Core Add-PSSnapin VMware.VimAutomation.Core Write-Verbose "Connecting to vCenter $vcentername" Connect-VIServer $vcentername -Credential $DomainAdministratorCredential if ($Ensure -eq "Present") { Write-Verbose "Creating Snapshots for all vm's in resource pool $resourcepoolname" $sn = Get-ResourcePool $resourcepoolname | Get-VM |% { New-Snapshot -Name $_.name -VM $_.name } Write-Verbose "Snapshots created for all vm's in resourcepool $resourcepoolname " Write-Verbose "$sn" } else { Write-Verbose "Removing Snapshots for all vm's in resource pool $resourcepoolname" Get-ResourcePool $resourcepoolname | Get-VM | Get-Snapshot | % {Remove-Snapshot $_ -Confirm:$false} Write-Verbose "All snapshots for VM's in resourcepool '$resourcepoolname' have been removed" } } catch { $exception = $_ Write-Verbose "An error occurred while running Set-TargetResource function" while ($exception.InnerException -ne $null) { $exception = $exception.InnerException Write-Verbose $exception.message } } } function Get-TargetResource { [OutputType([System.Collections.Hashtable])] param ( [parameter(Mandatory)] [string] $vcentername, [parameter(Mandatory)] [string] $resourcepoolname, [Parameter(Mandatory)] [PSCredential]$DomainAdministratorCredential ) Add-PSSnapin VMware.VimAutomation.Core Write-Verbose "Connecting to vCenter $vcentername" Connect-VIServer $vcentername -Credential $DomainAdministratorCredential $snapshotExist = Get-ResourcePool $resourcepoolname | Get-VM | Get-Snapshot $Configuration = @{ Snapshots = $snapshotExist } Write-Verbose "Checking if Snapshots exists for the VM's in resource pool " try { #Addpssnapin VMware.VimAutomation.Core $snapshotExist = Get-ResourcePool $resourcepoolname | Get-VM | Get-Snapshot if ($snapshotExist) { Write-Verbose "Snapshots exist for these VM's" $Configuration.Add('Ensure','Present') } else { Write-Verbose "Snapshots does not exist for these VM's" $Configuration.Add('Ensure','Absent') } return $Configuration } catch { $exception = $_ Write-Verbose "Error occurred while running Get-TargetResource function" while ($exception.InnerException -ne $null) { $exception = $exception.InnerException Write-Verbose $exception.message } } } Export-ModuleMember -Function *-TargetResource
Once you create the script module / .psm1 file which contains all the logic, save it as “DSC_PowerCLISnapShotCheck.schema.psm1”.
Once we have the script module created, next we need to generate the module manifest for the script module, this can be done via the New-ModuleManifest cmdlet.
$param = @{ guid = [Guid]::NewGuid() author = "Vinith" company = "PowerShell Guy!" moduleversion = "1.0" description = "DSC resource to manage and monitor snapshot across your environment" path= 'C:\Windows\System32\WindowsPowerShell\v1.0\Modules\DSC_PowerCLISnapShotCheck\DSC_PowerCLISnapShotCheck.psd1' } New-ModuleManifest @param
Once you generate all the required files, save each of the DSC resource components specified as per the below location.
Here’s a graphical view of how the module files are placed.
Once all the steps are done, lets head onto the grand finale 🙂 of invoking this DSC resource, i would be using the push method and the configured host will be the localhost itself, also note that you need to have PowerCLI installed on your system, you can check out one of my earlier post on DSC with PowerCLI to configure PowerCLI via DSC.
Ok so lets see the configuration which would be used to push the configuration across the systems, note that in production environment you would need to use certificate based authentication as its more secure.
$ConfigurationData = @{ AllNodes = @( @{ NodeName="localhost" PSDscAllowPlainTextPassword=$true } ) } Configuration PowerCLISnapshotCheckTest { param ( [Parameter(Mandatory)] [pscredential]$domainCred ) Import-DscResource -Name PowerCLISnapShotCheck Node localhost { PowerCLISnapShotCheck PowerCLI { resourcepoolname = "vinith*" vcentername = "vc-lab.corp.com" Ensure = "Absent" DomainAdministratorCredential = $domainCred } } } PowerCLISnapshotCheckTest -ConfigurationData $configurationData -OutputPath C:\scripts -domainCred (Get-Credential -Message "New Domain Admin Credentials") Start-DscConfiguration -Wait -Force -Verbose -Path C:\scripts
Next lets push the configurations using the below command.
Start-DscConfiguration -Wait -Force -Verbose -Path C:\scripts
Now in the above configuration we have kept Ensure = “Absent”, which when executed will make sure that if there are snapshots on the vm’s it would be deleted.
Here are some screen captures from the resource execution aka final victory in the war against DSC 🙂 .
Well, that’s the end of this blog post folks,hope you enjoyed it and gives you ideas to build your own custom DSC resources using PowerCLI.
PowerCLI DSC Resource
In the end always remember DSC resources are just PowerShell Modules :), and if you have the logic, you can build anything!
You can also download the Resource from PowerShell gallery
Do Check out my other posts on DSC and PowerCLI
Pingback: Automate PowerCLI Install across your Windows Environment using PowerShell DSC -Virtualize & Automate-
Hey Vinneth,
Nice blog post, can you please check this and let me know if you have any suggestions or feedback for same.
https://jatinpurohit.wordpress.com/2017/07/31/my-failed-attempt-with-powershell-dsc-vmware/
https://jatinpurohit.wordpress.com/2017/07/18/powershell-dsc-vmware-issue-with-script-resource/
Thanks
Jatin