# Logging variables$LogDirectory = "C:\script\Logs"$LogFilePrefix = "MSSQL_Cloning"$startTime = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"$logFileName = "$LogFilePrefix`_$startTime.log"$logFilePath = Join-Path -Path $LogDirectory -ChildPath $logFileName# Logging functionfunction Write-Log {param ([string]$Message,[switch]$IsError)# Log the message$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"$logMessage = "$timestamp - $Message"if ($IsError) {$logMessage = "$timestamp - ERROR: $Message"}Write-Output "$logMessage"Add-Content -Path $logFilePath -Value $logMessage}# Main Script# Clear old log filesWrite-Log "===== Script triggered ====="try {Remove-Item -Path "\\domain.com\failed.txt" -Force -ErrorAction StopRemove-Item -Path "\\domain.com\success.txt" -Force -ErrorAction StopWrite-Log "Old status logs file cleared"} catch {Write-Log "Failed to delete old log files: $_"}# Import PowerShell modulesImport-Module PureStoragePowerShellSDK2# Declare variables$TargetSQLServer = 'SqlServerHostName'$ArrayName = 'PureArrayName.domain.com'$ProtectionGroupName = 'PG-Clone'$PureUser = "Domain\User"#$File = "Password.txt"$Credential = Import-CliXml -Path "C:\script\cred.xml"Write-Log "Required variables decleared"$TargetDiskSerialNumbers = @("8A5123A4CA7E12345DC562F", "8A5123A4CA7E12345DC5630", "8A5123A4CA7E12345DC5631", "8A5123A4CA7E12345DC5632", "8A5123A4CA7E12345DC5829", "8A5123A4CA7E12345DC582A", "8A5123A4CA7E12345DC582B", "8A5123A4CA7E12345DC582C")$VolumesToCreate = @(@{ TargetVolumeName = "TargetSqlVolume-E-DATAFILES_DB04-33"; SourceVolumeName = "SourceSqlVolume-E-DATAFILES_DB04-26" },@{ TargetVolumeName = "TargetSqlVolume-F-LOGFILES_LOG01-34"; SourceVolumeName = "SourceSqlVolume-F-LOGFILES_LOG01-34" },@{ TargetVolumeName = "TargetSqlVolume-E-DATAFILES_DB03-35"; SourceVolumeName = "SourceSqlVolume-E-DATAFILES_DB03-25" },@{ TargetVolumeName = "TargetSqlVolume-F-LOGFILES_LOG01-36"; SourceVolumeName = "SourceSqlVolume-F-LOGFILES_LOG01-33" },@{ TargetVolumeName = "TargetSqlVolume-E-DATAFILES_DB08-37"; SourceVolumeName = "SourceSqlVolume-E-DATAFILES_DB08-210" },@{ TargetVolumeName = "TargetSqlVolume-F-LOGFILES_LOG01-38"; SourceVolumeName = "SourceSqlVolume-F-LOGFILES_LOG01-38" },@{ TargetVolumeName = "TargetSqlVolume-E-DATAFILES_DB010-39"; SourceVolumeName = "SourceSqlVolume-E-DATAFILES_DB010-212" },@{ TargetVolumeName = "TargetSqlVolume-F-LOGFILES_LOG01-310"; SourceVolumeName = "SourceSqlVolume-F-LOGFILES_LOG01-310" }# Additional volumes as needed)Write-Log "Target pure volumes serial numbers declared:"Write-Log "$TargetDiskSerialNumbers"$DatabaseNames = @("DB1","Db2","DB3","DB4","DB5","DB6","DB7","DB9")Write-Log "Target DBs declared:"Write-Log "$DatabaseNames"# Initialize success flag$success = $trueWrite-Log "Pre-script initializations completed"try {# Offline the target databasesWrite-Log "===== Putting DBs offline ====="foreach ($DBName in $DatabaseNames) {try {Write-Log "Working with $DBName - trying to put offline."$Query = "ALTER DATABASE [$DBName] SET OFFLINE WITH ROLLBACK IMMEDIATE"Invoke-Sqlcmd -ServerInstance $TargetSQLServer -Database master -Query $Query -ErrorAction StopWrite-Log "Set $DBName offline."#Start-Sleep -Seconds 10} catch {Write-Log "Failed to set $DBName offline: $_"$success = $false}}Start-Sleep -seconds 10Write-Log "===== Verifying DBs are offline ====="try{# Join the array elements into a single string with quotes and commas$DatabaseNamesString = ($DatabaseNames -join "','")# Construct the SQL query$Query = "SELECT name, state_desc FROM sys.databases WHERE name IN('$DatabaseNamesString') AND state_desc NOT LIKE '%offline%'"# Run the query$db_status = Invoke-Sqlcmd -ServerInstance $TargetSQLServer -Database master -Query $Query -ErrorAction Stopif ($db_status.Count -eq 0){Write-Log "All required DBs are offline. Online DB count is - $($db_status.count)"} else {Write-Log "ERROR !!! NOT ALL required DBs are offline !!! Online DB count is - $($db_status.count)"#Write-Log $db_status#break}} catch {# Write-Log "Some of the DBs are not offline: $DBName is not offline: $_"# $success = $false}# Wait for 5 mins after offlining DB.Start-Sleep -seconds 300# Offline the target volumesWrite-Log "===== Putting Volumes offline ====="foreach ($SerialNumber in $TargetDiskSerialNumbers) {try {Write-Log "Working with Serial Number $SerialNumber - trying to put it offline."Get-Disk | Where-Object { $_.SerialNumber -eq $SerialNumber } | Set-Disk -IsOffline $True -AsJob -ErrorAction StopWrite-Log "Disk with Serial Number $SerialNumber is now offline."Start-Sleep -Seconds 5} catch {Write-Log "Failed to set disk with Serial Number $SerialNumber offline: $_"$success = $false}}# Connect to FlashArray and create a snapshotWrite-Log "===== Creating PURE storage snapshots ====="try {$FlashArray = Connect-Pfa2Array -Endpoint $ArrayName -Credential $Credential -IgnoreCertificateError -ErrorAction Stop$Snapshot = New-Pfa2ProtectionGroupSnapshot -Array $FlashArray -SourceName $ProtectionGroupName -ErrorAction StopWrite-Log "Snapshots created."} catch {Write-Log "Failed to create snapshot: $_"$success = $false}# Perform volume overwritesWrite-Log "===== Overwriting exisiting PURE volumes ====="foreach ($Volume in $VolumesToCreate) {try {$TargetVolumeName = $Volume.TargetVolumeName$SourceVolumeName = $Volume.SourceVolumeNameNew-Pfa2Volume -Array $FlashArray -Name $TargetVolumeName -SourceName ($Snapshot.Name + "." + $SourceVolumeName) -Overwrite $true -ErrorAction StopWrite-Log "Created volume $TargetVolumeName from snapshot of $SourceVolumeName."} catch {Write-Log "Failed to create volume $TargetVolumeName : $_"$success = $false}}Start-Sleep -seconds 10# Bring disks back onlineWrite-Log "===== Putting cloned disks on-line ====="foreach ($SerialNumber in $TargetDiskSerialNumbers) {try {Get-Disk | Where-Object { $_.SerialNumber -eq $SerialNumber } | Set-Disk -IsOffline $False -ErrorAction StopWrite-Log "Disk with Serial Number $SerialNumber is now Online."} catch {Write-Log "Failed to bring disk with Serial Number $SerialNumber online: $_"$success = $false}}Start-Sleep -Seconds 60# Bring databases back onlineWrite-Log "===== Putting DBs on-line ====="foreach ($DBName in $DatabaseNames) {try {$Query = "ALTER DATABASE [$DBName] SET ONLINE WITH ROLLBACK IMMEDIATE"Invoke-Sqlcmd -ServerInstance $TargetSQLServer -Database master -Query $Query -ErrorAction StopWrite-Log "Set $DBName Online."Start-Sleep -Seconds 5} catch {Write-Log "Failed to set $DBName online: $_"$success = $false}}# Cleanup snapshotWrite-Log " "try {Remove-Pfa2ProtectionGroupSnapshot -Array $FlashArray -Name $Snapshot.Name -ErrorAction Stop} catch {Write-Log "Failed to remove snapshot: $_"$success = $false}} catch {Write-Log "Script execution encountered a critical error: $_"$success = $false}# Verify if the required SMB share is accessibletry {$share_access = Get-Item "\\Domain.com\"} catch {Write-Log "Failed access the share: $_"$success = $false}# Create success or failure log file based on the outcomeif ($success) {New-Item -Path "\\Domain.com\success.txt" -ItemType File -ForceWrite-Log "Process completed successfully. Created success.txt."} else {New-Item -Path "\\Domain.com\failed.txt" -ItemType File -ForceWrite-Log "Process encountered errors. Created failed.txt."}Write-Log "===== Script finished ====="
0 Comments