Category Archives: 2017

Refreshing Important Unix/Linux Commands

This is refresher on the Unix/Linux commands which i use quite often. Hence, wanted to share them with fellow IT professionals.

Disk Usage

du -ah   display disk usage of all files and directories
du -ahc display disk usage of all file and directories and display total usage
du -mh   display disk usage in MB
du -sh   display the total used size in form of a summary
du -ahc —exclude=“*.txt”   exclude files from disk usage output
du -ahc —time   display the modification time in disk usage output

Secure Copy

Copy the file “snowy.txt” from a remote host to the local host
$ scp your_username@remotehost:snowy.txt /some/local/directory

Copy the file “snowy.txt” from the local host to a remote host
$ scp snowy.txt your_username@remotehost:/some/remote/directory

Copy the directory “tardis” from the local host to a remote host’s directory “bar”
$ scp -r tardis your_username@remotehost:/some/remote/directory/bar

Copy the file “snowy.txt” from remote host “rh1” to remote host “rh2”
$ scp your_username@rh1:/some/remote/directory/snowy.txt \
your_username@rh2:/some/remote/directory/

Copying the files “tardis.txt” and “bar.txt” from the local host to your home directory on the remote host
$ scp tardis.txt bar.txt your_username@remotehost:~

Copy the file “snowy.txt” from the local host to a remote host using port 2264
$ scp -P 2264 snowy.txt your_username@remotehost:/some/remote/directory

Copy multiple files from the remote host to your current directory on the local host
$ scp your_username@remotehost:/some/remote/directory/\{a,b,c\} .
$ scp your_username@remotehost:~/\{tardis.txt,bar.txt\} .

File Transfer Protocol (FTP)

Connect to FTP server and change local/remote directories
ftp IP/Hostname
ftp> bin
ftp> hash
Change remote server current directory
ftp> pwd
257 “/myftpserver” is current directory.
ftp> cd dir1
250 CWD command successful. “/myftpserver/dir1” is current directory.
ftp> pwd
257 “/myftpserver/dir1” is current directory.
Change local machine current directory
ftp> pwd
/home/thetecharch/FTP
ftp> lcd /tmp
Local directory now /tmp
ftp> pwd
/tmp
Download Files from FTP Server
ftp> ls
ftp> get FILENAME
ftp> mget *.html (download multiple files using mget)
ftp> mls *.html (view the file names before downloading)
Upload files to FTP Server
ftp> mput *.html
Close FTP connection
ftp> close
OR
ftp> bye

 

AWK Concepts

Files with TAB seperated columns
print 1st column of a file

awk ‘{print $1}’ messages
display two columns with a separator
awk ‘{print $1″ “$2}’ messages
print all the columns from a file, this is same like “cat messages”
awk ‘{print $0}’ messages

For “,” (csv) separated columns use “-F” or “FS” seperators
awk -F “,” ‘{print $1}’ BillingFile_20170103-0919-54.csv
awk ‘{print $1}’ FS=”,” BillingFile_20170103-0919-54.csv

Do no display the first column (Headers in a file)
awk ‘NR!=1{print $1″ “$2}’ FS=”,” BillingFile_20170103-0919-54.csv
Display all rows after row 20
awk ‘NR>20{print $1″ “$2}’ FS=”,” BillingFile_20170103-0919-54.csv
NR>=20 || NR<20 || NR<=20

match column value then filer data (matc column 3 with value 13)
awk ‘$3==’13′{print $0}’ messages | grep “vol006_smb02”
using OR
awk ‘$1==’13′ || $3==’10000′{print $0}’ messages
using AND (&&)

search for a specific string
awk -F “,” ‘/NAS/{print $0}’ BillingFile_20170103-0919-54.csv
excluding specific string
awk -F “,” ‘!/NAS/{print $0}’ BillingFile_20170103-0919-54.csv
awk -F “,” ‘!/au2106/ && !/AU2106/ && NR!=1{print $1}’ BillingFile_20170103-0919-54.csv
display all records where a string matches in a particular column
awk ‘$1~/Fri/{print $0}’ messages
search a string at beginning or end 
awk -F=”,” ‘$1!~/^N/{print $0}’ BillingFile_20170103-0919-54.csv
end: N$
using “if” statement

awk -F “,” ‘{if ($3>=20000) print $0}’ test.csv
awk -F “,” ‘BEGIN{salary=2}{if($3==10000){ $3=$3*2; print $0;}}’ test.csv
awk -F “,” ‘BEGIN{count=0}{if($3==10000) {count++;print $0}}END{print “Total Records: ” count}’ test.csv
 

Analyze messages file from NetApp Storage Controller

Download multiple messages files from storage controller on unix/linux host’s /tmp
$ cd /tmp
Consolidate multiple file in to one
$ cat $(ls -t) > outputfile.txt

Read a file, use “awk” to select a column in the file, sort the column contents and get unique values
$ cat outputfile.txt | awk ‘{print $6}’| sort | uniq -c | sort -rn
Read a file, use “grep” to search for string then use “awk” to select a column from the searched rows and display unique string with their count of occurrence
$ cat outputfile.txt | grep SNOWY02:wafl.volume.snap.autoDelete:info| awk ‘{print $9}’| sort | uniq -c | sort -rn
Read a file, use “grep” to search for string then use “awk” to select a column from the searched rows and display unique strings with customised output
$ cat SNOWY02_messages.txt | grep SNOWY02:wafl.volume.snap.autoDelete:info| awk ‘{print $9″ was deleted on “$1,$2,$3}’| uniq -c | sort -rn
Display anything within square brackets [ ]
cat snowy_02.txt | sed ‘s/.*\[\([^]]*\)\].*/\1/g’ | sort| uniq -c | sort -rn
 

Connect your Mac to Storage System’s Serial Console

Search for Serial Port
ls /dev/tty*
If that doesn’t work try this:
ioreg -c IOSerialBSDClient  | grep usb

Use screen from Mac Terminal to connect to storage system’s serial console
screen /dev/cu.usbserial 9600
Capture Screen Terminal Output on mac terminal:
script -a -t 0 out.txt screen /dev/ttyUSB0 115200
details
•script built in app to “make a typescript of terminal session”
•-a append to output file
•-t 0 time between writing to output file is 0 seconds, so out.txt is updated for every new char
•out.txt is just the output file name
•screen /dev/ttyUSB0 115200 – command from question for connecting to external device
you can then use tail to see that the file is updating
tail -100 out.txt
 

Activate Web Server on Mac

Mac OS comes installed with Python language. Python as a built in Web server which can be used to upload firmware files to storage controllers.
python -m SimpleHTTPServer 8000

Rendezvous with NetApp AFF A700 All Flash Array

A few days back i got an opportunity to visit Data Centre to setup NetApp AFF A700 All Flash Array. I was very exited. It’s been a long wait to get hands on with new shiny Flash Arrays from NetApp.
Although this storage system looks small in size, however, when it comes to peformance, it’s a beast.
We got this system for a POC (proof of concept), A700 storage controller and a Disk shelf with 3.8TB SSD drives.

I clicked some pictures while setting up the storage array.

A700 Front
A700-Front

A700 Rear
A700-Rear

Controller
Controller

Racked
Final

Hickups after Powering on the Storage Controller
After powering on the disk shelf and the storage controller, the console on my mac showed ASCII characters. I immediately figured out, this is an incorrect Baud Rate issue. The usual baud rate of 9600 is not going to work properly. After changing multiple values, i used the baud rate to setup NetApp E Series systems and it worked fine. It took about 1 hour to figure out the correct value. The documentation provided by NetApp didn’t have the proper Baud Rate value for connecting to storage console.

If any of you reading this post are going to be working with NetApp AFF A series systems please use the Baud Rate: 115200 for connecting to storage array console.

Powershell Script to Setup new NetApp clustered Data ONTAP system

Setting up a new NetApp clustered Data ONTAP system involves a number of steps. I have tried to automate these steps using NetApp Powershell toolkit. This saves time and reduces human errors while configuring new systems.
This script assumes that hardware is installed, “cluster setup” is run and all nodes joined in. I use a suffix of “-mgmt” with the cluster name when i configure a new clustered Data ONTAP system. This script has been tested to work with ONTAP 8.3 (simulators).

At present i have automated the following tasks:
    1.  Rename Nodes
2.  Rename root aggregates
3.  Create failover groups for cluster-mgmt and node-mgmt interfaces
4.  Add feature licenses
5.  Configure Storage Failover
6.  Unlock diag User
7.  Setup diag user password
8.  Create admin user for access to logs through http
9.  Setup Timezone and NTP server
10. Remove 10 Gbe ports from Default broadcast domain
11. Create ifgroups and add ports to ifgroups
12. Enable Cisco Discovery Protocol (cdpd) on all of the nodes
13. Setup disk auto assignment
14. Setup flexscale options
15. Disable flowcontrol on all the ports
16. Create data aggregates

The script displays the results on Powershell console as it iterates through the setup tasks. A transcript is also saved as a text file.

Cluster_config_screenshot

Source Code

 

<# .SYNOPSIS Automate Setup of a new NetApp clustered Data ONTAP cluster install .DESCRIPTION The script assumes the basic cluster setup is completed and all nodes joined. The script automates the following tasks: 1. Rename Nodes 2. Rename root aggregates 3. Create failover groups for cluster-mgmt and node-mgmt interfaces 4. Add feature licenses 5. Configure Storage Failover 6. Unlock diag User 7. Setup diag user password 8. Create admin user for access to logs through http 9. Setup Timezone and NTP server 10. Remove 10 Gbe ports from Default broadcast domain 11. Create ifgroups and add ports to ifgrps 12. Enable Cisco Discovery Protocol (cdpd) on all of the nodes 13. Setup disk auto assignment 14. Setup flexscale options 15. Disable flowcontrol on all the ports 16. Create data aggregates Example: PS C:\Users\vadmin\Documents\pshell-scripts> .\cluster_config_v1.5.ps1
.PARAMETER settingsFilePath
    Location of the File with User defined Parameters.
.EXAMPLE
    PS C:\Users\vadmin\Documents\pshell-scripts> .\cluster_config_v1.5.ps1
#>
#####################
# Declare Variables
#####################
$ClusterName             = "ntapclu1-mgmt"
$mgmtIP                  = "aa.bb.cc.dd"
$mgmtSubnet              = "aaa.bbb.ccc.ddd"
$mgmtGateway             = "aa.bb.cc.xx"
$ntpServer               = "ntp-server1"
$ClusterNameMgmtPort     = "e0d"
$NodeMgmtPort            = "e0c"
$timezone                = "Australia/Sydney"
[int]$maxraidsize        = 17 #raid group size for creating an aggregate
[int]$diskCount          = 51 
$TranscriptPath          = "c:\temp\cluster_setup_transcript_$(get-date -format "yyyyMMdd_hhmmtt").txt"
$licensesPath            = "c:\temp\licenses.txt" 
$ifgrp_a0a_port1         = "e0e"
$ifgrp_a0a_port2         = "e0f"
$timezone                = 'Australia/Sydney'

###########################
# Declare the functions
###########################
function Write-ErrMsg ($msg) {
    $fg_color = "White"
    $bg_color = "Red"
    Write-host " "
    Write-host $msg -ForegroundColor $fg_color -BackgroundColor $bg_color
    Write-host " "
}
#'------------------------------------------------------------------------------
function Write-Msg ($msg) {
    $color = "yellow"
    Write-host " "
    Write-host $msg -foregroundcolor $color
    Write-host " "
}
#'------------------------------------------------------------------------------
function Invoke-SshCmd ($cmd){
    try {
        Invoke-NcSsh $cmd -ErrorAction stop | out-null
        "The command completed successfully"
    }
    catch {
       Write-ErrMsg "The command did not complete successfully"
    }
}
#'------------------------------------------------------------------------------
function Check-LoadedModule {
  Param( 
    [parameter(Mandatory = $true)]
    [string]$ModuleName
  )
  $LoadedModules = Get-Module | Select Name
  if ($LoadedModules -notlike "*$ModuleName*") {
    try {
        Import-Module -Name $ModuleName -ErrorAction Stop
        Write-Msg ("The module DataONTAP is imported")
    }
    catch {
        Write-ErrMsg ("Could not find the Module DataONTAP on this system. Please download from NetApp Support")
        stop-transcript
        exit 
    }
  }
}
#'------------------------------------------------------------------------------
##############################
# Begin Cluster Setup Process
##############################
#'------------------------------------------------------------------------------
## Load Data ONTAP Module
start-transcript -path $TranscriptPath
#'------------------------------------------------------------------------------
Write-Msg  "##### Beginning Cluster Setup #####"
Check-LoadedModule -ModuleName DataONTAP
try {
    Connect-nccontroller $ClusterName -ErrorAction Stop | Out-Null   
    "connected to " + $ClusterName
    }
catch {
    Write-ErrMsg ("Failed connecting to Cluster " + $ClusterName + " : $_.")
    stop-transcript
    exit
}
#'------------------------------------------------------------------------------
## Get the nodes in the cluster
$nodes = (get-ncnode).node
#'------------------------------------------------------------------------------
## Rename the nodes (remove "-mgmt" string)
Write-Msg  "+++ Renaming Node SVMs +++"
foreach ($node in $nodes) { 
    Rename-NcNode -node $node -newname ($node -replace "-mgmt") -Confirm:$false |Out-Null
} 
Get-NcNode |select Node,NodeModel,IsEpsilonNode | Format-Table -AutoSize
$nodes = (get-ncnode).node
#'------------------------------------------------------------------------------
## Rename root aggregates
Write-Msg  "+++ Renaming root aggregates +++"
# get each of the nodes
Get-NcNode | %{ 
    $nodeName = $_.Node
    # determine the current root aggregate name
    $currentAggrName = (
        Get-NcAggr | ?{ 
             $_.AggrOwnershipAttributes.HomeName -eq $nodeName `
               -and $_.AggrRaidAttributes.HasLocalRoot -eq $true 
        }).Name
    # no dashes
    $newAggrName = $nodeName -replace "-", "_"
    # can't start with numbers
    $newAggrName = $newAggrName -replace "^\d+", " "
    # append the root identifier
    $newAggrName = "$($newAggrName)_root"
    if ($currentAggrName -ne $newAggrName) {
        Rename-NcAggr -Name $currentAggrName -NewName $newAggrName | Out-Null 
    }
    sleep -s 5
    Write-Host "Renamed aggregates containing node root volumes"
    (Get-NcAggr | ?{ $_.AggrOwnershipAttributes.HomeName -eq $node -and $_.AggrRaidAttributes.HasLocalRoot -eq $true }).Name 
}
#'------------------------------------------------------------------------------
## Create failover groups for cluster-mgmt and node-mgmt interfaces
Write-Msg  "+++ Create failover groups for cluster-mgmt and node-mgmt interfaces +++"
# get admin vserver name
$adminSVMTemplate = Get-NcVserver -Template
Initialize-NcObjectProperty -Object $adminSVMTemplate -Name VserverType | Out-Null
$adminSVMTemplate.VserverType = "admin"
$adminSVM         = (Get-NcVserver -Query $adminSVMTemplate).Vserver
# create cluster-mgmt failover group 
$clusterPorts     = ((get-ncnode).Node | % { $_,$ClusterNameMgmtPort -join ":" })
$nodePorts        = ((get-ncnode).Node | % { $_,$NodeMgmtPort -join ":" })
$firstClusterPort = $clusterPorts[0]
$allClusterPorts  = $clusterPorts[1..($clusterPorts.Length-1)]
New-NcNetFailoverGroup -Name cluster_mgmt -Vserver $adminSVM -Target $firstClusterPort | Out-Null
foreach ($cPort in $allClusterPorts) {
    Add-NcNetFailoverGroupTarget -Name cluster_mgmt -Vserver $adminSVM -Target $cPort | Out-Null
}
Set-NcNetInterface -Name cluster_mgmt -Vserver $adminSVM -FailoverPolicy broadcast_domain_wide -FailoverGroup cluster_mgmt | Out-Null
Write-Host "Created cluster-mgmt failover group"
Get-NcNetInterface -Name cluster_mgmt  | select InterfaceName,FailoverGroup,FailoverPolicy
# create node-mgmt failover-group for each node
foreach ($node in $nodes) {
    $prt1 = ($node,$NodeMgmtPort -join ":")
    $prt2 = ($node,$ClusterNameMgmtPort -join ":")
    New-NcNetFailoverGroup -Name $node"_mgmt" -Vserver $adminSVM -Target $prt1 | Out-Null
    Add-NcNetFailoverGroupTarget -Name $node"_mgmt" -Vserver $adminSVM -Target $prt2 | Out-Null
    $nodeMgmtLif = (Get-NcNetInterface -Role node-mgmt | Where-Object {$_.HomeNode -match "$node"}).InterfaceName
    Set-NcNetInterface -Name $nodeMgmtLif -Vserver $adminSVM -FailoverPolicy local-only -FailoverGroup $node"_mgmt" | Out-Null
    sleep -s 5
    Write-Host "Created node-mgmt failover group for node "$node
    Get-NcNetInterface -Role node-mgmt | Where-Object {$_.HomeNode -match "$node"} | select InterfaceName,FailoverGroup,FailoverPolicy
}
sleep -s 15
#'------------------------------------------------------------------------------
## Add licenses to cluster
Write-Msg "+++ Adding licenses +++"
$test_lic_path = Test-Path -Path $licensesPath
if ($test_lic_path -eq "True") {
    $count_licenses = (get-content $licensesPath).count
    if ($count_licenses -ne 0) {
        Get-Content $licensesPath |  foreach { Add-NcLicense -license $_ }
        Write-Host "Licenses successfully added"
        Write-Host " "
    }
    else {
        Write-ErrMsg ("License file is empty. Please add the licenses manually")
    }
}
else {
    Write-ErrMsg ("License file does not exist. Please add the licenses manually")       
}
sleep -s 15
#'------------------------------------------------------------------------------
## Configure storage failover
Write-Msg  "+++ Configure SFO +++"
Write-Host "SFO Does not work with Simulators"
if ($nodes.count -gt 2) {
    foreach ($node in $nodes) {
        $sfo_enabled = Invoke-NcSsh "storage failover modify -node " $node " -enabled true"
        if (($sfo_enabled.Value.ToString().Contains("Error")) -or ($sfo_enabled.Value.ToString().Contains("error"))) {
            Write-ErrMsg ($sfo_enabled.Value)
        }
        else {
            Write-Host ("Storage Failover is enabled on node " + $node)
        }

	    $sfo_autogive = Invoke-NcSsh "storage failover modify -node " $node " -auto-giveback true"
        if (($sfo_autogive.Value.ToString().Contains("Error")) -or ($sfo_autogive.Value.ToString().Contains("error"))) {
                Write-ErrMsg ($sfo_autogive.Value)
        }
        else {
            Write-Host ("Storage Failover option auto giveback is enabled on node " + $node)
            Write-Host " "
        }
        sleep -s 2
    }
}
elseif ($nodes.count -eq 2) {
    foreach ($node in $nodes) {
        $sfo_enabled = Invoke-NcSsh "cluster ha modify -configured true"
        if (($sfo_enabled.Value.ToString().Contains("Error")) -or ($sfo_enabled.Value.ToString().Contains("error"))) {
            Write-ErrMsg ($sfo_enabled.Value)
        }
        else {
            Write-Host ("Cluster ha is enabled on node " + $node)
            Write-Host
        }  
    }
}
else {
    Write-Host "No HA required for single node cluster. Continuing with the setup"
    Write-Host " "
}
sleep -s 15
#'------------------------------------------------------------------------------
## Unlock the diag user
Write-Msg "+++ Unlock the diag user +++"
try {
    Unlock-NcUser -username diag -vserver $ClusterName -ErrorAction stop |Out-Null
    Write-Host "Diag user is unlocked"
}
catch {
    Write-ErrMsg "Diag user is either unlocked or script could not unlock the diag user"
}
#'------------------------------------------------------------------------------
## Setup diag user password
Set-Ncuserpassword -UserName diag -password netapp123! -vserver $ClusterName | Out-Null
Write-Host "created diag user password"
sleep -s 15
#'------------------------------------------------------------------------------
## Create admin user for access to logs through http
Write-Msg "+++ create web log user +++"
Set-NcUser -UserName admin -Vserver $ClusterName -Application http -role admin -AuthMethod password | Out-Null
Write-Host "created admin user access for http log collection"
sleep -s 15
#'------------------------------------------------------------------------------
## Set Date and NTP on each node
Write-Msg  "+++ setting Timezones/NTP/Datetime +++"
foreach ($node in $nodes) {
    Set-NcTime -Node $node -Timezone $timeZone | Out-Null
    Set-NcTime -Node $node -DateTime (Get-Date) | Out-Null
}
New-NcNtpServer -ServerName $ntpServer -IsPreferred | Out-Null
Write-Host "NTP Sever setup complete"
sleep -s 15
#'------------------------------------------------------------------------------
## Remove 10 Gbe ports from Default broadcast domain
Write-Msg  "+++ Rmoving 10Gbe Ports from Default broadcast domain +++"
# remove ports from Default broadcast domain
$broadCastTemplate = Get-NcNetPortBroadcastDomain -Template
Initialize-NcObjectProperty -Object $broadCastTemplate -Name Ports | Out-Null
$broadCastTemplate.BroadcastDomain = "Default"
$defaultBroadCastPorts = ((Get-NcNetPortBroadcastDomain -Query $broadCastTemplate).Ports).Port
foreach ($bPort in $defaultBroadCastPorts) {
	if (($bPort -notlike "*$ClusterNameMgmtPort") -and ($bPort -notlike "*$NodeMgmtPort")) {
		Write-Host "Removing Port: " $bPort
		Set-NcNetPortBroadcastDomain -Name Default -RemovePort $bPort | Out-Null
	}	
}
sleep -s 15
#'------------------------------------------------------------------------------
## Create ifgroups and add ports to ifgrps
Write-Msg  "+++ starting ifgroup creation +++"
foreach ($node in $nodes) {
    try {
        New-NcNetPortIfgrp -Name a0a -Node $node -DistributionFunction port -Mode multimode_lacp -ErrorAction Stop | Out-Null
        Add-NcNetPortIfgrpPort -name a0a -node $node -port $ifgrp_a0a_port1 -ErrorAction Continue | Out-Null
        Add-NcNetPortIfgrpPort -name a0a -node $node -port $ifgrp_a0a_port2 -ErrorAction Continue | Out-Null
        Write-Host ("Successfully created ifgrp a0a on node " + $node)
    }
    catch {
        Write-ErrMsg ("Error exception in ifgrp a0a " + $node + " : $_.")
    }
}
sleep -s 15
#'------------------------------------------------------------------------------
## Enable cdpd on all of the nodes
Write-Msg  "+++ enable cdpd on nodes +++"
foreach ($node in $nodes) {
    $cdpd_cmd = Invoke-NcSsh "node run -node " $node " -command options cdpd.enable on"
    if (($cdpd_cmd.Value.ToString().Contains("Error")) -or ($cdpd_cmd.Value.ToString().Contains("error"))) {
        Write-ErrMsg ($cdpd_cmd.Value)
    }
    else {
        Write-Host ("Successfully modified cdpd options for " + $node)
    }
}
sleep -s 15
#'------------------------------------------------------------------------------
## Set option disk.auto_assign on
Write-Msg  "+++ Setting disk autoassign +++"
foreach ($node in $nodes) {
    $set_disk_auto = Invoke-NcSsh "node run -node " $node " -command options disk.auto_assign on"
    if (($set_disk_auto.Value.ToString().Contains("Error")) -or ($set_disk_auto.Value.ToString().Contains("error"))) {
        Write-ErrMsg ($set_disk_auto.Value)
    }
    else {
        Write-Host ("Successfully modified disk autoassign option on node " + $node)
    }   
}
sleep -s 15
#'------------------------------------------------------------------------------
## Set flexscale options
Write-Msg  "+++ Setting flexscale options +++"
foreach ($node in $nodes) {
	$flexscale_enable = Invoke-NcSsh "node run -node " $node " -command options flexscale.enable on" 
    if (($flexscale_enable.Value.ToString().Contains("Error")) -or ($flexscale_enable.Value.ToString().Contains("error"))) {
        Write-ErrMsg ($flexscale_enable.Value)
    }
    else {
        Write-Host ("options flexscale.enable set to on for node " + $node)
    } 

	$flexscale_lopri = Invoke-NcSsh "node run -node " $node " -command options flexscale.lopri_blocks on"
    if (($flexscale_lopri.Value.ToString().Contains("Error")) -or ($flexscale_lopri.Value.ToString().Contains("error"))) {
        Write-ErrMsg ($flexscale_lopri.Value)
    }
    else {
        Write-Host ("options flexscale.lopri_blocks set to on for node " + $node)
    } 

	$flexscale_data = Invoke-NcSsh "node run -node " $node " -command options flexscale.normal_data_blocks on"
    if (($flexscale_data.Value.ToString().Contains("Error")) -or ($flexscale_data.Value.ToString().Contains("error"))) {
        Write-ErrMsg ($flexscale_data.Value)
    }
    else {
        Write-Host ("options flexscale.normal_data_blocks set to on for node " + $node)
        Write-Host " "
    } 

}
sleep -s 15
#'------------------------------------------------------------------------------
## Disable flowcontrol on all of the ports
Write-Msg  "+++ Setting flowcontrol +++"
foreach ($node in $nodes) {
    try {
        Write-Host "Setting flowcontrol for ports on node: " $node
        get-ncnetport -Node $node | Where-Object {$_.Port -notlike "a0*"} | select-object -Property name, node | set-ncnetport -flowcontrol none -ErrorAction Stop | Out-Null
        sleep -s 15
        Get-NcNetPort -Node $node | Select-Object -Property Name,AdministrativeFlowcontrol | Format-Table -AutoSize
    }
    catch {
        Write-ErrMsg ("Error setting flowcontrol on node " + $node + ": $_.")
    }
}
sleep -s 15
#'------------------------------------------------------------------------------
## Create data aggregates
Write-Msg  "+++ Creating Data Aggregates +++"
# get each of the nodes
Get-NcNode | %{ 
    $nodeName = $_.Node
    # no dashes
    $newAggrName = $nodeName -replace "-", "_"
    # can't start with numbers
    $newAggrName = $newAggrName -replace "^\d+", " "
    # append the root identifier
    $newAggrName = "$($newAggrName)_data_01"
    # create an aggreagate
    $aggrProps = @{
        'Name' = $newAggrName;
        'Node' = $nodeName;
        'DiskCount' = $diskCount;
        'RaidSize' = $maxraidsize;
        'RaidType' = "raid_dp";
    }
    New-NcAggr @aggrProps | Out-Null
#
    sleep -s 15
    # enable free space reallocation
    Get-NcAggr $newAggrName | Set-NcAggrOption -Key free_space_realloc -Value on
}
#'------------------------------------------------------------------------------
Write-Host " "
Write-Host " "
stop-transcript
#'------------------------------------------------------------------------------

VMware ESXi 6.5 White Box Build

In the past few months i have been researching on upgrading my home lab esxi white box (Mac Mini Server Late 2012) to a white box with more available resources and capable of running VMware ESXi 6.5.
My Mac Mini had the limitation of 16 GB RAM max. So a need to expand my home lab arose. I still wanted to keep a single system to run virtual machines in my home lab. During my research i came across various builds posted by home lab enthusiasts on their blogs and reddit. However, availability of parts in Australia restricted my options. And finally i settled on the Motherboard and CPU which were reported to work with ESXi 6.0 and above out of the box. Making sure a suitable RAM was another big task for me, as it was the costliest component of all (i ordered 128 GB kit).

I share my experiences with those who might be interested to build their own ESXi white box at home.

Components Used:
PC_Components_List
  

For PC Parts i shopped around local stores in Australia:
Mwave
Scorptec
MSY
ebay
Gumtree

I had two Solid State Drives (250GB each) in my Mac Mini which i imported to the new White box. I ran CPU and Memory Stress Tests on the new build and everthing reported normal. The softwares i used for RAM and CPU tests provided a bootable iso file. I booted from a USB drive and ran all tests without installing any Operating System. I used Rufus to create bootable USB drives.
RAM Test: Memory Test (RAM)
CPU Test: CPU Stress Test

I registered the virtual machines on the SSD’s in my new White Box and i was up and runnig with my new lab in seconds.

Picture of my Build

PC_Build

VMware ESXi 6.5 has a fully functional Web Client built in. There is no longer a need to connect a new ESXi host via vSphere client.

ESXi

 

Hope you find this post useful.