Introduction
Hello to all readers of the SDDC and Architecture, Solution, Implementation and Operations as Code blog.
Today, I will continue to talk about such a conceptual approach as Operations as Code as a component of the Anything as Code strategy.
In the previous post, Anything as code: Upload File to ESXi Datasore, I talked about the function that performs the task of uploading a file to the ESXi datasore. Functions are passed to the input the necessary parameters in the form of a variable, changing which you can also use a code reuse strategy.
Today we will take the next step and consider the following situation: The file is uploaded to the datastore of the hypervisor, but during operation we observe some errors. So I want to be sure that the file was uploaded correctly. To do this, you need to calculate the hash of the file and compare it with the correct one.
Moreover, for the efficiency of the work process, this action should be performed on the hypervisor side with the appropriate built-in tools.
So, for your attention, the PowerShell function Check-UploadedFileHash.
Check-UploadedFileHash
So let’s look at the code for the Check-UploadedFileHash function:
Function Check-UploadedFileHash {
<#
.SYNOPSIS
Check file Hash Uploaded to ESXi datastore.
.DESCRIPTION
Check file Hash Uploaded to ESXi datastore.
.PARAMETER Target
Name or IP Address of the VMware ESXi.
.PARAMETER File
Name of file.
.PARAMETER Datastore
Name of ESXi Datastore.
.PARAMETER Folder
Name of ESXi Datastore Folder.
.PARAMETER Algorithm
Algorithm for calculate Hash.
.PARAMETER Hash
Reference File Hash.
.NOTES
Version: 0.1
Author: Andrii Romanenko
Website: blogs.airra.net
Creation Date: 10.08.2023
Purpose/Change: Initial script development
Version: 0.2
Author: Andrii Romanenko
Change Date: 02.01.2024
Purpose/Change: Purpose/Change: Reorganize Function. Add Workflow Time Measuring External Function: Get-CalculateWorkingTime.
Add ValidateSet $Algorithm in Input Parameters
Add Case Algorithm Command and Output
Version: 0.3
Author: Andrii Romanenko
Change Date: 08.01.2024
Purpose/Change: Purpose/Change: Reorganize Function. Rename function name to Check-UploadedFileHash and some variables.
.EXAMPLE
$Parameters = @{
Target = $ESXiHost
Datastore = $ISODatastore
Folder = "ISO\"
File = "en_windows_8_1_x64_dvd_2707217.iso"
Algorithm = "SHA256"
Hash = "23DCCB255FA73CE6E93B12FEFEEFB7204C1681B9A343B51126D3D79F3A34BCD3"
}
Check-UploadedFileHash @Parameters
$Parameters = @{
Target = $ESXiHost
Datastore = $ISODatastore
Folder = "ISO\"
File = "en_windows_8_1_x64_dvd_2707217.iso"
Algorithm = "MD5"
Hash = "f104b78019e86e74b149ae5e510f7be9"
}
Check-UploadedFileHash @Parameters
$Parameters = @{
Target = $ESXiHost
Datastore = $ISODatastore
Folder = "ISO\"
File = "en_windows_8_1_x64_dvd_2707217.iso"
Algorithm = "SHA1"
Hash = "bc2f7ff5c91c9f0f8676e39e703085c65072139b"
}
Check-UploadedFileHash @Parameters
$Parameters = @{
Target = $ESXiHost
Datastore = $ISODatastore
Folder = "ISO\"
File = "en_windows_8_1_x64_dvd_2707217.iso"
Algorithm = "SHA512"
Hash = "25446f98ea6cf35e95ecb0cb3ff9584e67c252d78ca0ac98f08e97d9aa62ddf537ea9c55f6e730abfa09b5759c16d4d2a6ad64ff356a62db914495f203b92807"
}
Check-UploadedFileHash @Parameters
#>
param (
[Parameter(Mandatory)][string]$Target,
[Parameter(Mandatory)][string]$File,
[Parameter(Mandatory)][string]$Datastore,
[Parameter(Mandatory)][string]$Folder,
[Parameter(Mandatory)][ValidateSet('SHA1','SHA256','SHA512','MD5')][string]$Algorithm,
[Parameter(Mandatory)][string]$Hash
)
# Get start time of the Check File Hash operation
$StartTime = Get-Date
$Message = "Begin Check Hash: " + $Image + " on Datastore: " + $Datastore + " on Target:" + $Target + "."
Write-Host -ForegroundColor Green $Message
# Check if SSH service on ESXI is running
$SSHServiceStatus = Get-VMHost | Get-VMHostService | Where { $_.Key -eq "TSM-SSH" }
If ($SSHServiceStatus.Running -eq "True")
{
$Message = "SSH Service is running. Nothing To Do."
Write-Host -ForegroundColor Green $Message
}
Else
{
$Message = "SSH Service is NOT running. Starting Service"
Write-Host -ForegroundColor Red $Message
Get-VMHost | Get-VMHostService | Where { $_.Key -eq "TSM-SSH" } | Start-VMHostService
}
# Open SSH session
$Message = "Open SSH Session to host: " + $Target + "."
Write-Host -ForegroundColor Green $Message
$SSHSession = New-SSHSession -ComputerName $Target –AcceptKey -Credential $Script:ESXISessionCredentials
# Check File Hash
$Message = "Begin Calculate Hash of file: " + $File + " on Datastore: " + $Datastore + "."
Write-Host -ForegroundColor Green $Message
# Get Datasore ID
$DataStoreID = (Get-VMHost | Get-Datastore -Name $Datastore)
$DataStoreID = $DataStoreID.ID.Substring(10)
# Case AlgoritmCommand
Switch ($Algorithm) {
"SHA1" { $AlgorithmCommand = "sha1sum"}
"SHA256" { $AlgorithmCommand = "sha256sum"}
"SHA512" { $AlgorithmCommand = "sha512sum"}
"MD5" { $AlgorithmCommand = "md5sum"}
}
$SSHCommand = $AlgorithmCommand
$SSHCommand += ' /vmfs/volumes/'
$SSHCommand += $DataStoreID
$SSHCommand += '/'
$SSHCommand += $Folder.Replace("\", "/")
$SSHCommand += $File
$Result = Invoke-SSHCommand -SSHSession $SSHSession -Command $SSHCommand
#Write-Host $Result.Output
# Case Algoritm Output
Switch ($Algorithm) {
"SHA1" { $HashResult = $Result.Output.Substring(0,40)}
"SHA256" { $HashResult = $Result.Output.Substring(0,64)}
"SHA512" { $HashResult = $Result.Output.Substring(0,128)}
"MD5" { $HashResult = $Result.Output.Substring(0,32)}
}
$Message = "End Calculate Hash of file: " + $File + " on Datastore: " + $Datastore + "."
Write-Host -ForegroundColor Green $Message
# Check Result
$Message = "Begin Check Hash of file: " + $File + "."
Write-Host -ForegroundColor Green $Message
$Result=$HashResult.ToUpper().Equals($Hash.ToUpper())
If ($Result -eq "True")
{
$Message = "Hash Valid"
Write-Host -ForegroundColor Green $Message
}
Else
{
$Message = "Hash Not Valid"
Write-Host -ForegroundColor Red $Message
}
$Message = "End Check Hash of file: " + $File + "."
Write-Host -ForegroundColor Green $Message
# Remove SSH Session
$Message = "Close SSH Session to host: " + $Target + "."
Write-Host -ForegroundColor Green $Message
Remove-SSHSession $SSHSession | Out-Null
# Get end time of the operation
$EndTime = Get-Date
# Calculate Elapsed Time of the operation
Get-CalculateWorkingTime -StartTime $StartTime -EndTime $EndTime
}
The function accepts the following mandatory parameters as input in the form of the @Parameters variable:
- Target – Name or IP Address of the VMware ESXi;
- File – Checked File Name;
- Datastore – Name of ESXi Datastore;
- Folder – Name of ESXi Datastore Folder;
- Algorithm – Algorithm for calculate Hash;
- Hash – Reference File Hash.
At the beginning of work, the start time is fixed in the form of the $StartTime variable.
The function will use the Posh-SSH Powershell module for its work to connect to the ESXi hypervisor and execute commands in the SSH environment. Therefore, the next step is to check whether this service is running on the hypervisor side, and if not, to start it.
This action is performed by standard PowerCLI cmdlets Get-VMHost, Get-VMHostService, Start-VMHostService.
Next, open an SSH session to the ESXi host New-SSHSession. This cmdlet is already from the Posh-SSH module.
For the algorithm to calculate the hash of the file, you will need to specify the path to the location of the file on the ESXi datastore. To do this, you should get a datastore identifier:
$DataStoreID = (Get-VMHost | Get-Datastore -Name $Datastore)
$DataStoreID = $DataStoreID.ID.Substring(10)
Different algorithms can be used to calculate the hash of a file. Their list is limited to the input variable $Algorithm and contains the following values: ‘SHA1′,’SHA256′,’SHA512′,’MD5’.
Depending on the value of the variable, the appropriate command will be used: sha1sum, sha256sum, sha512sum, md5sum. The Switch ($Algorithm) Powershell structure helps in this.
The $SSHCommand variable forms a command that should be sent to the SSH session. The result of the SSH Command goes into the $Result variable.
Depending on the hash calculation algorithm, the variable will contain a text fragment of different lengths. Therefore, depending on the $Algorithm variable, the required number of characters will be allocated. What will correspond to the calculated hash: sha1sum – Substring(0.40), sha256sum – Substring(0.64), sha512sum – Substring(0,128), md5sum – Substring(0,32).
Finally, the calculated hash is compared with the reference value from the $Hash variable. The result is displayed as Hash Valid or Hash Not Valid in green and red, respectively.
At the end of the work, we delete the SSH Session and calculate the duration of work with the Get-CalculateWorkingTime function, which I talked about in the previous post.
The result of the function is shown in the following figure:
Brief Summary
So, in today’s post, I’ve shared with you some code snippets that demonstrate the strategy and practice of Operations as Code.
I note that you can use this code at your discretion, adding there, for example, verification codes and handling of exceptional situations, etc.
Also, don’t forget that the function requires the presence of the VMware PowerCLI and Posh-SSH.
That’s all for today. Follow the next publications of this direction.
Follow the news until the meeting is on air in a few days.
Sincerely, AIRRA.