Category Archives: Storage

DELL Perc H710P Local Storage SSD RAID1 Benchmark

Recently we have equipped one of our ESXi hosts with local SSD storage (Product Number: LB806M) to host a database VM. For redundancy we have chosen RAID1. I have done a small benchmark to compare it to already present 4x 1,2TB 10k RPM (PN: ST1200MM0007) RAID10 array.

The RAID Controller serving the drives was DELL Perc H710P Mini (Dual processor, 1GB DDR3 NV Cache). I have used the IOmeter application with Access Specification File from my favorite tech-news aggregate site, TechPowerUp. I have run the test on a 1GB Chunk of data. Without further ado, here are the results (click on an image to enlarge):

Throughput Benchmark

Throughput Benchmark

IOPs Benchmark

IOPs Benchmark

Latency Benchmark

Latency Benchmark

Also, I’ve captured a few interesting screenshots from esxtop over the course of benchmarks. Notice that the controller doesn’t even break a sweat under that many IOPS:

Installing the Windows VM for benchmarking

Installing the Windows VM for benchmarking

Database Benchmark on the Mechanical Hard DRive and SSD running simultaneously.

Database Benchmark on the Mechanical Hard DRive and SSD running simultaneously.

Nice IOPS :)

Nice IOPS 🙂

Sequential Read Benchmark - the Controller Cache comes into play.

Sequential Read Benchmark – the Controller Cache comes into play.

Hope you enjoyed the numbers. See you around.

Scripting Corner: NetApp Storage Controller Option Setter

Last week I have introduced to you NetApp Storage Controller Options Retriever – now it is the time to show you how to push a bulk amount of options to the NetApp Storage Controller via PowerShell. As with the previous post, you will need the Data OnTap PowerShell Toolkit.

The input of this script is a .csv file containing Option and Value columns – these must match exactly the options you wish to set and a valid value going along with it. The next imput is controllers.txt where your controllers you want to apply options to are written, with line break as a separator. A sample .csv is shown below:

Option;Value
cf.takeover.on_failure;on
cf.takeover.on_network_interface_failure;off
cf.giveback.auto.delay.seconds;600

And below is the script itself:

# The Module DataOntap is needed for this script to function.

# Define a function to push the given option
function Push-NaOption ($option, $value)
{
	Try
	{
		Set-NaOption -OptionName $option -OptionValue $value | Out-Null
	}
	Catch
	{
	Write-Host There was an error setting the $option on $sc. -ForegroundColor 'red'
	}
}

Write-Host `n "--- NetApp Option Pusher ---" -ForegroundColor 'Cyan' `n
$startedtime = Get-Date

# Generate a new array for controller list and fill it
$sclist = @()
$sclist += Get-Content controllers.txt

# Do the same with the options array
$CSV = Import-Csv optionstopush.csv

Write-Host 'Started pushing options to' $sclist.count 'Storage Controllers' `n

# Initialize failed controllers array
$failedcount = 0
$failednames = @()

# Start pushing the options
ForEach ($sc in $sclist)
{
	# Verify if the connection has been successful, if not increase the failed counter and add the name to array.
	Try
	{
		Connect-NaController $sc -ErrorAction 'SilentlyContinue' | Out-Null
		Write-Host "Processing Controller $sc" -ForegroundColor Green
		if ($global:CurrentNaController -eq $null)
		{
			Write-Host "Could not connect to Controller $sc ! Skipping..." -ForegroundColor Red
			$failedcount++
			$failednames += $sc
			Continue
		}

	}
	# Also catch an exception if it was thrown.
	Catch
	{
		Write-Host "Could not connect to Controller $sc ! Skipping..." -ForegroundColor Red
		$failedcount++
		$failednames += $sc
		Continue
	}

	ForEach ($line in $CSV)
	{
		Push-NaOption $line.Option $line.Value
	}

}

# Count statistics...
$endedtime = Get-Date
$timetook = ($endedtime - $startedtime).TotalSeconds

$scOK = $sclist.count - $failedcount

# Final stat listing.
Write-Host `n Processed $scOK Storage Controllers 'in' $timetook seconds. -ForegroundColor Green
If ($failedcount -ge 1)
{
	Write-Host `n "Connection to the following $failedcount controllers failed: " $failednames `n -ForegroundColor 'Red'
}

Hope this saved you some headache trying to push any amount of options to a large number of NetApp Storage Controllers.

Scripting Corner: NetApp Storage Controller Options Retriever

Once upon a time we had to make a revision of some options on about 50 NetApp Storage Controllers in our environment. The options were many and we needed to retrieve them in a reviewable fashion to mark out which comply to NetApp’s best practices.

You will require NetApp’s Data OnTap Powershell Toolkit in order for this script to run, because it uses their commandlets.

It took me four days to devise this script, mainly because I had other things to do like resolving incidents and doing actual work 😀 The hardest part was the looping and writing to CSV. This script has a few caveats:

  • If you search for just one option, the CSV will not be generated properly, so enter a random second option, input the same one or just an asterisk will do (the fields will be blank).
  • It is better if you take the CSV and invert it – better readability and searchability, however I have realized that after the script has been finished. And I’d rather not return to the cycling nightmare again 🙂
  • The CSV is generated procedurally inside a variable and is output to a file at the end of the script – if you stop it while running halfway, you get no partial CSV.

The sample output can  be found below:

A sample output from options collected by the script - not transposed.

A sample output from options collected by the script – not transposed.

You will need two input files – controllers.txt with the controllers you want to query and options.txt with options you wish to retrieve – the separator is a line break. Please note that the options must be input exactly as they appear in Data OnTap, else the script can misbehave. I hope many of you will find this script useful.

Import-Module DataONTAP

Write-Host `n "--- NetApp Option Retriever ---" -ForegroundColor 'Cyan' `n
$startedtime = Get-Date

#Define path to the exported CSV.
$csvpath1 = ".\options.csv"

# Generate a new array for controller list and fill it
$sclist = @()
$sclist += Get-Content controllers.txt

# Do the same with the options array
$optIN = @()
$optIN += Get-Content options.txt

Write-Host 'Started gathering' $OptIN.count 'options on' $sclist.count 'Storage Controllers' `n

# A base for list of options we want to find
$optcmd = "Get-NaOption | Sort | Select Name, Value"

# Create an array from the options we want to find by first sorting it out...
$optIN = $optIN | Sort

# ...And then formatting it like a CSV
$datasuffix = @("Data;")

# Fill in the first column of the CSV
foreach ($item in $optIN)
{
	$datasuffix += "$item" + ";"
}

# Intialize the array with first column
$CachedCsv = @()
$CachedCsv += $datasuffix

# Initialize empty array for the ignored fields
$ignored = @()

# Initialize failed filers value
$failedcount = 0
$failednames = @()

# Procedure to write all the CSV values using procedural CSV construction
ForEach ($sc in $sclist)
{
	Try
	{
		Connect-NaController $sc -ErrorAction 'SilentlyContinue' | Out-Null
		Write-Host "Processing Controller $sc" -ForegroundColor Green
		if ($global:CurrentNaController -eq $null)
		{
			Write-Host "Could not connect to Controller $sc ! Skipping..." -ForegroundColor Red
			$failedcount++
			$failednames += $sc
			Continue
		}

	}
	Catch
	{
		Write-Host "Could not connect to Controller $sc ! Skipping..." -ForegroundColor Red
		$failedcount++
		$failednames += $sc
		Continue
	}

	#Generate another column header = storage controller name
	$CachedCsv[0] += $sc + ";"

	# run the stored command
	$getvalues = Invoke-Expression $optcmd

	# Clear the IGNORED array
	$ignored.clear()

	# For each value got...
	for ($i = 0; $i -lt $getvalues.count; $i++)
	{
		# Search this value's name in the input options array
		for ($j = 0; $j -lt $optIN.count; $j++)
		{
			# And if it matches exactly, write it there
			if ($getvalues[$i].name -contains $optIN[$j])
			{
				$presentIndex = [array]::IndexOf($optIn, $optIN[$j])
				$CachedCSV[$presentindex + 1] += $getvalues[$i].value + ";"
			}
			# If the value we are looking for does not exist, write an empty field and enter that value in the $ignored array
			# So it does not get checked over and over again.
			ElseIf (($getvalues.name -notcontains $optIN[$j]) -and ($ignored -notcontains $optIN[$j]))
			{
				$ignored += $optIN[$j]
				$missingIndex = [array]::IndexOf($optIn, $optIN[$j])
				$CachedCSV[$missingindex+1] += ";"
			}
		}
	}
}

# Write out the cached CSV
"Sep=;" | Out-File $csvpath1
$CachedCsv | Out-File $csvpath1 -Append

# Count statistics...
$endedtime = Get-Date
$timetook = ($endedtime - $startedtime).TotalSeconds

$scOK = $sclist.count - $failedcount

# Final stat listing.
Write-Host `n Processed $OptIN.count options on $scOK Storage Controllers 'in' $timetook seconds. -ForegroundColor Green
If ($failedcount -ge 1)
{
	Write-Host `n "Connection to the following $failedcount controllers failed: " $failednames `n -ForegroundColor 'Red'
}

And of course, since there is an option Retriever for NetApp, there must also be an option setter, right? Yes you are correct and that will be a subject of a future Scripting Corner 🙂 See you soon!