Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
**VMFS/VMDK + SQL Server Snapshot Scripts**
<p align="center"></p>
This folder contains VMFS/VMDK + SQL Server example snapshot scripts.

**Files:**
- VMFS-VMDK Snapshot.ps1

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

**Scenario:**
<BR>This example script shows steps to snapshot a VMFS datastore that contains data & log VMDKs for a SQL Server. The overall scenario is taking a snapshot of a production SQL Server's underlying datastore, and cloning the datastore to then overlay a pre-existing non-production datastore for a non-production SQL Server.

All references to a "target" refer to the non-production side (VM, datastore, etc).

**Prerequisites:**
1. The production datastore must already be cloned and presented once, to the non-production side.
2. This script assumes the database(s) are already attached on the target, non-production SQL Server.

**Important Usage Notes:**
<BR>You must pre-setup the target VM with a cloned datastore from the source already. You will ONLY be utilizing the specific VMDK(s) that contain the data/log files of interest, from the cloned datastore. Also note that the VMFS datastore does not need to only exclusively contain VMDKs for the SQL Server in question. If other VMDKs are present in the datastore, used by the either the source SQL Server VM or other VMs, they do not need to be deleted or otherwise manipulated during this cloning process. Remember FlashArray deduplicates data, thus a clone's set of additional, unused VMDKs will not have a negative impact.

For the cloned datastore pre-setup, you can use subsets of the code below to clone the source datastore, present it to the target server, then attach the VMDK(s) containing the production databases that will be re-cloned with this script. Once "staged," you can then use this script fully to refresh the data files in the cloned datastore that is attached to the target server.

When cloning, note that the target datastore is dropped and replaced entirely. This is because when cloning a datastore, it must be resignatured and the datastore will be renamed with a non-deterministic naming scheme (snap-[[GUID chars]]-[[original DS name]]). Thus it is not possible to know what the new datastore name will be until the resignature step is executed.

This script also assumes that all database files (data and log) are on the same volume/single VMDK. If multiple volumes/VMDKs are being used, you will have to adjust the code (ex: add additional foreach loops for manipulating multiple VMDKs).

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

**Disclaimer:**
<BR>
This example script is provided AS-IS and meant to be a building block to be adapted to fit an individual organization's infrastructure.
<BR>
<BR>

We encourage the modification and expansion of these scripts by the community. Although not necessary, please issue a Pull Request (PR) if you wish to request merging your modified code in to this repository.

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

_The contents of the repository are intended as examples only and should be modified to work in your individual environments. No script examples should be used in a production environment without fully testing them in a development or lab environment. There are no expressed or implied warranties or liability for the use of these example scripts and templates presented by Pure Storage and/or their creators._
171 changes: 171 additions & 0 deletions demos-archive/VMFS-VMDK Snapshot/VMFS-VMDK Snapshot - V1.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
##############################################################################################################################
# Refresh VMFS VMDK with Snapshot Demo
#
#
# Scenario:
# Snapshot and clone a "production" VMDK in a VMFS datastore, then present it to a "non-production" server.
#
# This example has two databases: ExampleDb1, ExampleDb2, whose data and log files both reside on a single disk/VMDK.
#
#
# Usage Notes:
#
# You must pre-setup the target VM with a cloned datastore from the source already. You will ONLY be utilizing
# the SPECIFIC VMDK(s) that contain the data/log files of interest, from the cloned datastore. Other VMDKs can safely be
# ignored since they are deduped on FlashArray.
#
# For the cloned datastore pre-setup, you can use subsets of the code below to clone the source datastore, present it to
# the target server, then attach the VMDK(s) containing the production databases that will be re-cloned with this script.
# Once "staged," you can then use this script fully to refresh the data files in the cloned datastore that is attached
# to the target server.
#
# This script also assumes that all database files (data and log) are on the same volume/single VMDK. If multiple
# volumes/VMDKs are being used, adjust the code to add additional foreach loops when manipulating the VMDKs.
#
# 2025/12/22: AYun - Renamed to "VMFS-VMDK Snapshot - V1.ps1" and migrated to archive in
# PureStorage-OpenConnect\sqlserver-scripts\demos-archive\VMFS-VMDK Snapshot
#
# Disclaimer:
# This example script is provided AS-IS and meant to be a building block to be adapted to fit an individual
# organization's infrastructure.
##############################################################################################################################



# Import powershell modules
Import-Module PureStoragePowerShellSDK2
Import-Module VMware.VimAutomation.Core
Import-Module SqlServer



# Declare variables
$TargetVM = 'SqlServer1' # Name of target VM
$Databases = @('ExampleDb1','ExampleDb2') # Array of database names
$TargetDiskSerialNumber = '6000c02022cb876dcd321example01b' # Target Disk Serial Number
$VIServerName = 'vcenter.example.com' # vCenter FQDN
$ClusterName = 'WorkloadCluster1' # VMware Cluster
$SourceDatastoreName = 'vmware_sql_datastore' # VMware datastore name
$SourceVMDKPath = 'SqlServer1_1/SqlServer1.vmdk' # VMDK path inside the VMFS datastore
$ArrayName = 'flasharray1.example.com' # FlashArray FQDN
$SourceVolumeName = 'sql_volume_1' # Source volume name on FlashArray (may be same as your datastore name)
$TargetVolumeName = 'sql_volume_2' # Target volume name on FlashArray (may be same as your datastore name)



# Set Credential - this assumes the same credential for the target VM and vCenter
$Credential = Get-Credential



# Create a Powershell session against the target VM
$TargetVMSession = New-PSSession -ComputerName $TargetVM -Credential $Credential



# Connect to vCenter
$VIServer = Connect-VIServer -Server $VIServerName -Protocol https -Credential $Credential



# Offline the target database(s) by looping through $Databases array
foreach ($Database in $Databases) {
$Query = "ALTER DATABASE [$Database] SET OFFLINE WITH ROLLBACK IMMEDIATE"
Invoke-Sqlcmd -ServerInstance $TargetVM -Database master -Query $Query
}



# Offline the volumes that have SQL data
Invoke-Command -Session $TargetVMSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber } | Set-Disk -IsOffline $True }



# Prepare to remove the VMDK from the VM
$VM = Get-VM -Server $VIServer -Name $TargetVM
$HardDisk = Get-HardDisk -VM $VM | Where-Object { $_.FileName -match $SourceVMDKPath }



# Remove the VMDK from the VM
Remove-HardDisk -HardDisk $HardDisk -Confirm:$false



# Prepare to remove the stale datastore
$DataStore = $HardDisk.Filename.Substring(1, ($HardDisk.Filename.LastIndexOf(']') - 1))
$Hosts = Get-Cluster $ClusterName | Get-VMHost | Where-Object { ($_.ConnectionState -eq 'Connected') }



# Guest hard disk removed, now remove the stale datastore - this can take a min or two
Get-Datastore $DataStore | Remove-Datastore -VMHost $Hosts[0] -Confirm:$False



# Connect to the array, authenticate. Remember disclaimer at the top!
$FlashArray = Connect-Pfa2Array -Endpoint $ArrayName -Credential ($Credential) -IgnoreCertificateError



# Perform the volume overwrite (no intermediate snapshot needed!)
New-Pfa2Volume -Array $FlashArray -Name $TargetVolumeName -SourceName $SourceVolumeName -Overwrite $True



# Rescan storage on each ESX host in the $Hosts array
foreach ($VmHost in $Hosts) {
Get-VMHostStorage -RescanAllHba -RescanVmfs -VMHost $VmHost | Out-Null
}



# Connect to EsxCli
$esxcli = Get-EsxCli -VMHost $Hosts[0]



# Resignature the cloned datastore
$EsxCli.Storage.Vmfs.Snapshot.Resignature($SourceDatastoreName)



# Find the assigned datastore name, this may take a few seconds
# NOTE: when a datastore comes back, it's name will be "snap-[GUID chars]-[original DS name]"
# This is why the wildcard match below is needed.
$DataStore = (Get-Datastore | Where-Object { $_.Name -match 'snap' -and $_.Name -match $SourceDatastoreName })



# Rescan storage again to make sure all hosts can see the new datastore
foreach ($VmHost in $Hosts) {
Get-VMHostStorage -RescanAllHba -RescanVmfs -VMHost $VmHost | Out-Null
}



# Attach the VMDK from the newly cloned datastore back to the target VM
New-HardDisk -VM $VM -DiskPath "[$DataStore] $SourceVMDKPath"



# Online the volume on the target VM
Invoke-Command -Session $TargetVMSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber } | Set-Disk -IsOffline $False }



# Volume might be read-only, ensure it's read/write
Invoke-Command -Session $TargetVMSession -ScriptBlock { Get-Disk | Where-Object { $_.SerialNumber -eq $using:TargetDiskSerialNumber } | Set-Disk -IsReadOnly $False }



# Online the target database(s) by looping through $Databases array
foreach ($Database in $Databases) {
$Query = "ALTER DATABASE [$Database] SET ONLINE WITH ROLLBACK IMMEDIATE"
Invoke-Sqlcmd -ServerInstance $TargetVM -Database master -Query $Query
}



# Remove powershell session
Remove-PSSession $TargetVMSession
Loading
Loading