#This script file is intended to provide a single page status of vDisk replication

#This script was created by Rob Zylowski Citrix CCS
#
#Although every effort has been made to ensure that these sample scripts work properly, 
#Citrix disclaims any responsibility for any and all liability or responsibility for any 
#damages that may result from using these scripts. 
#The sample scripts are provided to you as is, with no warranty or guarantees.
#
#Updated 1-20-2019
#Fixed screen output to remove some verbose logging
#Added the date/time of the run to the report that show up in the header

#Updated 9-5-2019
#Fixed entries that have load balancing disabled

function DatatableToHTML ($dt)

{ 
	$html +="<tr>"
	
	#Lets write out the column headings
	for($i = 0;$i -lt $dt.Columns.Count;$i++)
	{
		$html += "<td>"+$dt.Columns[$i].ColumnName+"</td>" 
	}
	$html +="</tr>"

	for($i=0;$i -lt $dt.Rows.Count; $i++)
	{
		$html +="<tr>"
		 for($j=0; $j -lt $dt.Columns.Count; $j++)
		 {
		 	$Caption = $dt.Columns[$j].Caption
			$Value = $dt.Rows[$i][$j].ToString()
			#if ($Value -eq ""){continue}
			if (($Caption -eq "Version") -or ($Caption -eq "vDisk"))
			{
				if ($Caption -eq "vDisk")
				{
					$html += "<td align='left' style='width:350px'>$Value</td>"
				}
				elseIf ($Caption -eq "Version")
					{
						$html += "<td align='center'  style='width:60px'>$Value</td>"
					}
					else
					{
						$html += "<td align='center'  style='width:120px'>$Value</td>"
					}
			}
			else
			{
				if ($Value -eq "0")
				{
					$html += "<td align='center'><img src=""$global:imagefolder\bluecircle.jpg""></img>&nbsp;$Value</td>"
				}
				elseIf ($Value -eq "")
				{
					$html += "<td align='center'><img src=""$global:imagefolder\greencircle2.jpg""></img>&nbsp;6 </td>"
				}
				else
				{
					$html += "<td align='center'><img src=""$global:imagefolder\redx.jpg""></img>&nbsp;$Value </td>"
				}
			}
		 }
	 	$html +="</tr>"
	}
	return $html
}


function Get-ScriptDirectory
#This gets the current directlry which we use to store the text data files
{
 $Invocation = (Get-Variable MyInvocation -Scope 1).Value
 Split-Path $Invocation.MyCommand.Path
}


Write-Host ""
Write-Host "Running Replication Status Report"
Write-Host ""

$ScriptSource = Get-ScriptDirectory
$global:imagefolder = "$ScriptSource\..\images"
$ReplStatusFile = "$ScriptSource\..\config\replstatus.html"

$datetime = Get-Date -Format F
try{
    Import-Module 'C:\Program Files\Citrix\Provisioning Services console\Citrix.PVS.SnapIn.dll' -ErrorAction Stop
} catch {
    Write-Host "PVS PowerShell Snap-In Not Found on $env:computername.  Script terminated."
	exit
}

#Lets set up the header for our html output file
$h = "<!DOCTYPE html>
	<html>
	<head>
	<style>
	 H1 { font-family:Verdana,Arial,Helvetica,Sans-Serif; font-size:medium; }
     H2 { font-family:Verdana,Arial,Helvetica,Sans-Serif;font-size:small; }
     p { font-family:Verdana,Arial,Helvetica,Sans-Serif; font-size:small;margin:0;padding:0 }
	table, th, td {
	    border: 1px solid black;
	    border-collapse: collapse;
		font-family:Verdana,Arial,Helvetica,Sans-Serif; font-size:small;
	}
	</style>
	</head>
	<body>
	<h2 style='color:blue'>PVS Replication Status as of <font color='Black'>$datetime</font></h2>"

#Get the Master master Server.  This is the source of all teh replications.
$Masters = Get-Content "$ScriptSource\..\config\masters.txt"

#Loop thorugh the Master Servers to get sites, servers and stores.
foreach ($MasterServer in $Masters)
{
	Write-Host "Connecting to Master Server [$MasterServer]"
	Set-PvsConnection -Server $MasterServer
	$MySites = Get-PvsSite
	foreach ($SiteInfo in $MySites)
	{
		$Site = $SiteInfo.SiteName
		Write-Host "Getting Stores for site [$Site]"
		$MyStores = Get-PvsStore 
		
		foreach ($StoreInfo in $MyStores)
		{
			$Store = $StoreInfo.StoreName
			Write-Host "Getting PVS Servers for Store [$Store]"
			$t+="<h2><font color='Blue'>Master Server:&nbsp;</font><b>$MasterServer</b>&nbsp;&nbsp;&nbsp;<font color='Blue'>Site:&nbsp;</font><b>$Site</b>&nbsp;&nbsp;&nbsp;<font color='Blue'>Store:&nbsp;</font><b>$Store</b></h2>"
			$t+="<table cellpadding=""10"" border=""1"">"
			$PVSServers = Get-PvsServer  -StoreName $Store -SiteName $Site
			Write-Host "Getting vDisks for Store [$Store]"
			$DL_Array = Get-pvsdisklocator -StoreName $Store -SiteName $Site
			#If there are no vdisks in this store skip this entry
			if ($DL_Array.count -eq 0){continue}
			if ($DL_Array.count -gt 0)
			{
				$DL_Array_Sorted = $DL_Array | Sort-Object -Property DiskLocatorName
			}
			else
			{
				$DL_Array_Sorted = $DL_Array
			}
			$ReplColumns = New-Object System.Collections.ArrayList

			$Global:ReplTable = New-Object system.Data.DataTable "ReplTable"
			$ReplColumns.Add("vDisk")>$null
			$ReplColumns.Add("Version")>$null
			foreach ($Server in $PVSServers)
			{
				$ReplColumns.Add($Server.Name)>$null
			}
			ForEach ($Column in $ReplColumns) {$ReplTable.Columns.Add($(New-Object system.Data.DataColumn $Column,([string])))}
			ForEach ($Column in $ReplTable.Columns) {$Column.DataType = [Object]}

			$TableRow = $ReplTable.NewRow()
			$FirstTime = $True
			foreach ($DiskLocator in $DL_Array_Sorted)
			{
				#Write-Host $DiskLocator
				$LastDiskVersion = ""
				$LastDiskLocatorName = ""
				$DiskInventoryArray = Get-PvsDiskInventory -DiskLocatorId $DiskLocator.DiskLocatorId 
				foreach ($Disk in $DiskInventoryArray)
				{
					
					Foreach ($ServerInstance in $PVSServers)
					{
						if ($Disk.ServerName -eq $ServerInstance.ServerName)
						{
							if (($Disk.Version -ne $LastDiskVersion) -or ($DiskLocator.Name -ne $LastDiskLocatorName))
							{	
							if ($DiskLocator.Name -eq $null){continue}
								if (!$FirstTime)
								{
									$ReplTable.Rows.Add($TableRow)
									$TableRow = $ReplTable.NewRow()
								}
							}
							$TableRow.vDisk = $Disklocator.DiskLocatorName
							$vDiskName = $Disklocator.DiskLocatorName
							$DiskServerName = $Disk.ServerName
							$TableRow.Version = $Disk.Version
							$vDiskVersion = $Disk.Version
							$TableRow.$DiskServerName = $Disk.State
							Write-Host "PVSServer: $DiskServerName vDisk: $vDiskName  Version:$vDiskVersion"
							
							$FirstTime = $False
							$LastDiskVersion = $Disk.Version
							$LastDiskLocatorName = $DiskLocator.Name
						}
					}
				}
			}
			#Lets add the last row
			$ReplTable.Rows.Add($TableRow)
			#Now lets convert the datatable to hmtl
			if ($TableRow.vDisk -ne $null)
			{
				$t += DatatableToHTML -dt $ReplTable
				$t +="</table>"
			}
		}
	}
}

##writing html table to a html file 
$f += "</table><p>&nbsp;</p><p>The tables above list each vDisk and its replication status. Status codes are defined as follows: 0 = up to date, 1 = version file is 
missing, 2 = version file is out of date, 3 = properties are missing, 4 = properties are out of date, 5 = server 
is not reachable, 6 = no load balancing configured.</p></body></html>"
 
$h+$t+$f | out-file $ReplStatusFile -Encoding ASCII

Write-Host "Process Complete"

Sleep 3

#Notes on State
#0 (Up to date)
#1 (version file is missing)
#2 (version file is out of date)
#3 (properties are missing)
#4 (properties are out of date)
#5 (server is not reachable).
#6 (no load balancing configured)
