<# This is a different approach to the problem of how to get the data from a 'sysstat -x -c nn 1' output so that we can do bunches of controllers in one shot, have the output columns line up correctly and send the result as an email message to folks. This provide a framework for doing this with other command output when we need to. Paul Clayton March 2016 Mod 1 = add in the cluster controller code - March 2016 #> Function Get_The_Sysstat_Data ($controller_name, $cmdoutput, $row_to_start ) { <# This is the main work loop that does the heavy lifting to collect and format the sysstat output. #> # We will define some working variables that will be needed along the way # This one defines the structure and how the data is presented inside a tabular box for the resulting sysstat output. We are using this # method so that the different columns will automagically get lined up under one another and under the column headers $box_layout = "" #Replacement header rows in compressed text file of the sysstat output. We need to establish uniqueness between all column header text strings # otherwise the imports and references to the data will get confused and complained about. Note that we ADDED '__' entries for columns that # did NOT have any characters for the column. We needed to do this so that they all lined up correctly in the array and resulting output. $header_line_1 = "CPU NFS CIFS HTTP Total Net N_kB/s Disk D_kB/s Tape T_kB/s Cache- Cache CP- CP Disk_ OTHER FCP iSCSI FCP- F_kB/s iSCSI_ i_kB/s" $header_line_2 = "__ __ __ __ __ in out read write read write age hit time ty util __ __ __ in out in out" # Start the file off with checking for previously existing one and deleting if found along with writing the first two lines of header info. Note # that while this is a 'csv' (comma seperated) file type, in reality, it is space " " seperated file contents. #if the working file exists, we need to delete it so we get new data into it $File_csv = "C:\temp\$controller_name" + ".csv" #define the CSV file name we will use here $File_htm = "C:\temp\$controller_name" + ".htm" #define the HTML file name we will use here If (Test-Path $File_csv) { Remove-Item $File_csv } #and delete the file if we find it already exists since we want a clean set of data If (Test-Path $File_htm) { Remove-Item $File_htm } #and delete the file if we find it already exists since we want a clean set of data # The first challenge is that we now have a RAW string of data with 'returns' on it that we need to write out to # and then read back so that we get ONE line of text per index on the variable we read the data into. So we are # going to write out to the CSV file and then read it back in. This recreates the variable we are using from one long # string to one that is an array of lines that we can then deal with later on. $cmdoutput | Out-File -FilePath $File_csv #write out to we get 1 record per line on input $cmdoutput = Get-Content $File_csv #and read it back so we can use it # Now we need to get rid of all the multiple space characters there between the data that we received, so we use a regexp to work that magic $cmdoutput = $cmdoutput -replace '\s+', ' ' # And now we will do the steps needed to restart the CSV file in the format we need to read it back in as a multi-dimensional # array that can be fed into the HTML conversion routine. SO we delete the file and start it off correctly. If (Test-Path $File_csv) { Remove-Item $File_csv } #and delete the file if we find it already exists since we want a clean set of data $header_line_1 | out-file -filepath $File_csv -append #output first line of headers $header_line_2 | Out-File -FilePath $File_csv -Append #and the second line of headers. # And now we need to trim off the leading and training space characters from each line. We can do this at the same time we write the result to # a disk file so that we can cheat on creating a new array with correct column headers and delimiters set the way we want them. We will skip # the first two lines and then do '$iteration_cnt' rows as we do NOT want the original column headers as they won't work later on. for ( $ii = $row_to_start ; $ii -le $cmdoutput.count - 2 ; $ii++ ) { $cmdoutput[$ii].Trim() | Out-File -FilePath $File_csv -Append #add this line to the file } # Now we can import the newly created, custom headered, compressed, 'csv' file that has " " DELIMITER between columns in order to create # an array that we can quickly and and easily convert into a very nicely formatted box! $array = @(Import-CSV -Delimiter " " $File_csv) # And since we have the newly minted array with all the right properties, column headers and such, we will convert this into an HTML file in one shot! $array| ConvertTo-Html -head $box_layout -Property CPU,NFS,CIFS,HTTP,Total,Net,N_kB/s,Disk,D_kB/s,Tape,T_kB/s,Cache-,Cache,CP-,CP,Disk_,OTHER,FCP,iSCSI,FCP,F_kB/s,iSCSI_,i_kB/s |Set-Content $File_htm $sysstat_html = Get-Content -Path $File_htm # Do some cleanup, such as deleting the CSV file that we no longer need. The HTM file we still need. If (Test-Path $File_csv) { Remove-Item $File_csv } #clean up after ourselves If (Test-Path $File_htm) { Remove-Item $File_htm } #clean up after ourselves #use @' and '@ to surround the following string definintion so that we can use double quotes within the string itself and NOT have problems. $header_html = @'

Here is the "sysstat -x" data for controller {0}

'@ -f $controller_name # Now we will combine the existing contents of '$email_body' with the new data for this next controller so we get # an ever increasing amount of HTML code that provides for seperation between the charts and what the data is. $global:email_body = $global:email_body + $header_html + $sysstat_html # Keep building on the resulting HTML parts into one big redult. # All done the job of formatting the sysstat data from the controller and creating a REAL NICE box of the result in HTML format! Return } <# --------------------------------------------------------------------------------------------------- *** Main loop that controls the overall data collection, keeps track of growing HTML output and emails the results The following is the driver for getting the data. It defines what controllers to loop through, gets the sysstat command output and sends it to a Function in order to get the HTML boxes and columns to line up correctly for looking at. #> # We will define the list of controller names we want to play with since we are doing this interactively and start full HTML string empty $controller_list = "7modecontroller1","7modecontroller2","7modecontroller3", "cDOT_cluster_name1" $OnTap_mode = "7mode", "7mode", "7mode", "cdot" #start off with saying we are working on 7Mode controllers $global:email_body = "" #start the variable off with nothing, this grows in size for each controller $cmd_string = "sysstat -x -c 7 1" #define the sysstat command line that we will use in all cases. # And now we will do each of the controllers or cluster names we have defined above so that each is included in the output. For ($i = 0; $i -lt $controller_list.Count; $i++ ) { $controller_name = $controller_list[$i] #get the controller name $ontap_type = $OnTap_mode[$i] #and if it is 7Mode or cDOT <# The user creds to log into the different controllers is being handled outside of this script, so all we need to do if specify the name of the controller(s) that we want to get the sysstat data from. There is a good article about this mechanism that can be found at: http://practical-admin.com/blog/powershell-netapp-dataontap-toolkit-credentials-management/ #> if ( $ontap_type -eq "7mode" ) { $nacontroller=connect-nacontroller -Name $controller_name # Now go get the sysstat raw text output from the controller! Note that we need to pause the script execution for a bit so that # the output can be collected! There is no means for the 'invoke-nassh' command to know when the remote command terminates. $cmdoutput = invoke-nassh -command $cmd_string # format the resulting output and add to the body of the email $controller_html = (Get_The_Sysstat_Data $controller_name $cmdoutput 2 ) } else { #we have a cluster and need to do each node in the cluster $nccontroller = Connect-NcController -Name $controller_name #connect to the cluster first... $cluster_nodes = Get-NcNode #now get the list of controllers in the cluster foreach ( $cluster_node in $cluster_nodes ) { $cmdoutput = Invoke-NcSsh "node run -node $cluster_node -command `"$cmd_string`"" #get the actual sysstat output # format the resulting output and add to the body of the email $controller_html = (Get_The_Sysstat_Data $cluster_node $cmdoutput 5 ) } } } #curiously, when you dump the complete HTML code to a file and open the file in a browser, all the boxes show up just fine around each #controllers reulting output. But when the mail message is displayed, every other box has no lines around it at all! Weird. Still usable, #but very weird. #$email_body | Out-File c:\temp\sysstat.htm #uncomment to dump out the resulting file someplace to see what it looks like # Now we will send this email message to folks so they can review it. $smtpServer = "your_email_server_front_end" $smtpFrom = "some_legit_email_address@company.com" $smtpTo = "your_email_address@company.com" $messageSubject = "sysstat Performance Data For Various NetApp (7Mode/Cluster) Controllers" $message = New-Object System.Net.Mail.MailMessage $smtpfrom, $smtpto $message.Subject = $messageSubject $message.IsBodyHTML = $true $message.Body = $global:email_body $smtp = New-Object Net.Mail.SmtpClient($smtpServer) $smtp.Send($message) # __________________________________________________________________________________________________________________________________