PowerCLI DSC Resource for Snapshot check.

PowerCLI DSC Resource for Snapshot check.

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.

PowerCLI DSC Resource

Here’s a graphical view of how the module files are placed.

test

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 🙂 .

test

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

Share this post

2 thoughts on “PowerCLI DSC Resource for Snapshot check.

Post Comment