Adding Custom Scripts to DataCore Installation Manager for vSphere Deployment
DataCore Installation Manager for vSphere supports the use of custom PowerShell scripts for advanced configuration during deployment. You can automate settings and install dependencies by placing scripts in designated folders. Scripts run either on the DataCore Installation Manager for vSphere machine or inside the deployed virtual machines (such as DataCore SANsymphony Virtual Machines) at the appropriate stage of deployment.
- Scripts for DataCore Installation Manager for vSphere Machine: You must place scripts in the C:\Program Files\DataCore\vSphereInstallationManager\CustomScripts directory. These scripts run on the DIM-V machine during the deployment process.
- Scripts for Guest Virtual Machines (example; For SANSymphony Virtual Machines): To run custom scripts inside deployed virtual machines, such as SANsymphony Virtual Machines, you must place the PowerShell scripts in the C:\Program Files\DataCore\vSphereInstallationManager\CustomScripts\GuestOS directory before starting the deployment.
Scripts must be placed in the correct folders before running the deployment, and their filenames must follow the naming convention: dimv-<scriptname>.ps1 (e.g., dimv-DisableLogging.ps1).
Disable “Enable Logging” for SANSymphony Virtual Machines
To enhance the performance of deployed DataCore SANsymphony virtual machines, it is recommended to disable the Enable Logging setting during deployment. By default, this setting is enabled and may increase I/O activity and CPU usage, particularly under heavy workloads.
Disabling this setting reduces unnecessary disk writes and overhead, resulting in improved responsiveness and efficiency of the SANSymphony virtual machines.
Required Scripts
- dimv-PowerCLI-1.ps1: Installs the PowerCLI module if not already installed.
- dimv-PowerCLI-2.ps1: This script connects to the vCenter and disables the "Enable Logging" setting for all DataCore SANsymphony virtual machines by updating their virtual machine configuration.
-
Place the dimv-PowerCLI-1.ps1 script in the CustomScripts folder located at C:\Program Files\DataCore\vSphereInstallationManager\CustomScripts.
Copy#Check if PowerCLI is installed. If not then Install
$scriptName = "dimv-PowerCLI-1"
$runtime = (get-date -Format 'hh-mm-dd-MM-yyyy')
$logfile = "C:\" + "$scriptName" + "-" + "$runtime" + '.txt'
function Write-Log ($msg)
{
Write-Host $msg
Add-Content -Path $logfile -Value $msg
}
function LoadModule
{
[CmdletBinding()]
param (
[Parameter()]
[string]$Name,
[Parameter()]
[Version]$MinVersion
)
# If module is imported say that and do nothing
if (Get-Module | Where-Object {($_.Name -eq $Name) -and ($_.Version -ge $MinVersion)}) {
Write-Log "Module $Name with MinVersion: $MinVersion is already imported."
}
else {
# If module is not imported, but available on disk then import
if (Get-Module -ListAvailable | Where-Object {($_.Name -eq $Name) -and ($_.Version -ge $MinVersion)}) {
Write-Log "Module $Name is already installed. It will be imported."
Import-Module $Name -Verbose -MinimumVersion $MinVersion
}
else {
# If module is not imported, not available on disk, but is in online gallery then install and import
if (Find-Module -Name $Name | Where-Object {($_.Name -eq $Name) -and ($_.Version -ge $MinVersion)}) {
Write-Log "Module $Name is not installed. It will be installed and imported."
Install-PackageProvider NuGet -Force;
Set-PSRepository PSGallery -InstallationPolicy Trusted
Install-Module -Name $Name -Force -Verbose -Scope CurrentUser -AllowClobber -SkipPublisherCheck -MinimumVersion $MinVersion
Import-Module $Name -Verbose -MinimumVersion $MinVersion
}
else {
# If the module is not imported, not available and not in the online gallery then abort
Write-Log "Module $Name not imported, not available and not in an online gallery, exiting."
EXIT 1
}
}
}
}
LoadModule -Name "VMware.PowerCLI" -MinVersion ([Version]"13.2.0") -
Place the dimv-PowerCLI-2.ps1 script in the CustomScripts folder located at C:\Program Files\DataCore\vSphereInstallationManager\CustomScripts .
#Sets VMs enableLogging=false
#Creds: CHANGE THESE SETTINGS WHEN NEEDED
$Server = "vsphere.domain.local"
$Username = "Administrator@vsphere.local"
$Password = "Password123"
[pscredential]$creds = New-Object System.Management.Automation.PSCredential ($Username, (ConvertTo-SecureString $Password -AsPlainText -Force) )
$scriptName = "dimv-PowerCLI-2"
$runtime = (get-date -Format 'hh-mm-dd-MM-yyyy')
$logfile = "C:\" + "$scriptName" + "-" + "$runtime" + '.txt'
function Write-Log ($msg)
{
Write-Host $msg
Add-Content -Path $logfile -Value $msg
}
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null
Write-Log "This script is very destructive! It will delete all Windows VMs in the vCenter and remove many other things."
Write-Log "Current connections: $global:DefaultVIServers"
Write-Log "Removing all vCenter connections" # This is to ensure that this script only gets run on the vCenter that the user enters.
if ($null -ne $global:DefaultVIServers)
{
Disconnect-VIServer -Server $global:DefaultVIServers -Force -Confirm:$false
}
# Connect to a vCenter.
Write-Log "Connecting to vCenter: $Server"
Connect-VIServer -Server $Server -Credential $creds
Write-Log "Current connections: $global:DefaultVIServers"
$vms = Get-VM | Where-Object {$_.ExtensionData.Config.Annotation -match "DataCore Virtual SAN Server" -or $_.ExtensionData.Config.Annotation -match "DataCore SANsymphony Server" }
$vms | ForEach-Object {
$vm = $_
#Shut Down the VM
Write-Log "Shutting down the VM: $($vm.Name)"
$vm | Stop-VM -Confirm:$false | out-null
#Change the VM Settings
# Set Enable Logging = false
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$flags = New-Object VMware.Vim.VirtualMachineFlagInfo
$flags.EnableLogging = $false
$spec.Flags = $flags
$vm.ExtensionData.ReconfigVM($spec)
#Start the VMS
$vm | Start-VM -Confirm:$false | Out-Null
Write-Log "Starting up in the VM: $($vm.Name)"
#Ping the VMs
while (!(Test-Connection -ComputerName $($vm.Name) -Quiet -Count 1 -BufferSize 16))
{
Write-Log "[$(get-date -format u)] Waiting for $($vm.Name) to be reachable"
Start-Sleep -Seconds 30
}
Write-Log "[$(get-date -format u)]$($vm.Name) is reachable:)"
}
Once the scripts are placed and the DataCore Installation Management for vSphere deployment is complete, the "Enable Logging" setting will be disabled for all DataCore SANsymphony virtual machines.
Set “Latency Sensitivity” Setting to "High with HyperThreading"
To optimize CPU resource allocation on ESXi hosts, you can set the "Latency Sensitivity" to "High with HyperThreading" using custom scripts. This improves CPU efficiency by utilizing both physical and logical cores.
Example:
If 6 physical cores must be reserved, configure the VM to use 12 vCPUs and set the CPU reservation to 6x the frequency.
The ESXi host will provide 6 physical cores + 6 logical cores to the guest OS, leading to more efficient use of CPU resources.
- The virtual machine compatibility must be version 20 or greater (vSphere 8).
- This setting should not be executed on vSphere 7.
Required Scripts
- dimv-PowerCLI-1.ps1 – Installs the PowerCLI module if not already installed.
- dimv-PowerCLI-3.ps1- This script sets the "Latency Sensitivity" setting to "High with HyperThreading”.
-
Place the dimv-PowerCLI-1.ps1 script in the CustomScripts folder located at C:\Program Files\DataCore\vSphereInstallationManager\CustomScripts.
Copy#Check if PowerCLI is installed. If not then Install
$scriptName = "dimv-PowerCLI-1"
$runtime = (get-date -Format 'hh-mm-dd-MM-yyyy')
$logfile = "C:\" + "$scriptName" + "-" + "$runtime" + '.txt'
function Write-Log ($msg)
{
Write-Host $msg
Add-Content -Path $logfile -Value $msg
}
function LoadModule
{
[CmdletBinding()]
param (
[Parameter()]
[string]$Name,
[Parameter()]
[Version]$MinVersion
)
# If module is imported say that and do nothing
if (Get-Module | Where-Object {($_.Name -eq $Name) -and ($_.Version -ge $MinVersion)}) {
Write-Log "Module $Name with MinVersion: $MinVersion is already imported."
}
else {
# If module is not imported, but available on disk then import
if (Get-Module -ListAvailable | Where-Object {($_.Name -eq $Name) -and ($_.Version -ge $MinVersion)}) {
Write-Log "Module $Name is already installed. It will be imported."
Import-Module $Name -Verbose -MinimumVersion $MinVersion
}
else {
# If module is not imported, not available on disk, but is in online gallery then install and import
if (Find-Module -Name $Name | Where-Object {($_.Name -eq $Name) -and ($_.Version -ge $MinVersion)}) {
Write-Log "Module $Name is not installed. It will be installed and imported."
Install-PackageProvider NuGet -Force;
Set-PSRepository PSGallery -InstallationPolicy Trusted
Install-Module -Name $Name -Force -Verbose -Scope CurrentUser -AllowClobber -SkipPublisherCheck -MinimumVersion $MinVersion
Import-Module $Name -Verbose -MinimumVersion $MinVersion
}
else {
# If the module is not imported, not available and not in the online gallery then abort
Write-Log "Module $Name not imported, not available and not in an online gallery, exiting."
EXIT 1
}
}
}
}
LoadModule -Name "VMware.PowerCLI" -MinVersion ([Version]"13.2.0") -
Place the dimv-PowerCLI-3.ps1 script in the CustomScripts folder located at C:\Program Files\DataCore\vSphereInstallationManager\CustomScripts.
Copy#Sets VMs Latency Sensitivity to "High with HT"
#For this the Simultaneous threads property should be same as CPU number
#Creds: CHANGE THESE SETTINGS WHEN NEEDED
$Server = "vsphere.domain.local"
$Username = "Administrator@vsphere.local"
$Password = "Password123"
[pscredential]$creds = New-Object System.Management.Automation.PSCredential ($Username, (ConvertTo-SecureString $Password -AsPlainText -Force) )
$scriptName = "dimv-PowerCLI-3"
$runtime = (get-date -Format 'hh-mm-dd-MM-yyyy')
$logfile = "C:\" + "$scriptName" + "-" + "$runtime" + '.txt'
function Write-Log ($msg)
{
Write-Host $msg
Add-Content -Path $logfile -Value $msg
}
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null
Write-Log "This script is very destructive! It will delete all Windows VMs in the vCenter and remove many other things."
Write-Log "Current connections: $global:DefaultVIServers"
Write-Log "Removing all vCenter connections" # This is to ensure that this script only gets run on the vCenter that the user enters.
if ($null -ne $global:DefaultVIServers)
{
Disconnect-VIServer -Server $global:DefaultVIServers -Force -Confirm:$false
}
# Connect to a vCenter.
Write-Log "Connecting to vCenter: $Server"
Connect-VIServer -Server $Server -Credential $creds
Write-Log "Current connections: $global:DefaultVIServers"
$vms = Get-VM | Where-Object {$_.ExtensionData.Config.Annotation -match "DataCore Virtual SAN Server" -or $_.ExtensionData.Config.Annotation -match "DataCore SANsymphony Server" }
$vms | ForEach-Object {
$vm = $_
$hardwareVersion = $vm.HardwareVersion
$HardwareNumber = [int]($hardwareVersion | Select-String -Pattern "\d+$").Matches.Value
if ($HardwareNumber -ge 21 )
{
#Shut Down the VM
Write-Log "Shutting down the VM: $($vm.Name)"
$vm | Stop-VM -Confirm:$false | out-null
#Change the VM Settings
# Set SimultaneousThreads = Num of CPU
$vmResourceConfig = $vm | Get-VMResourceConfiguration
Write-Log "VM Resource configuration for $($vm.Name):`n $($vmResourceConfig | Out-String)"
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$simulatenousThreads = 2
$spec.SimultaneousThreads = $simultaneousThreads
$spec.NumCoresPerSocket = 0 # To avoid this error when CPU is 4 - High with Hyperthreading latency sensitivity requires the manual CPU Topology settings such as Cores per Socket and Cores per NUMA node to be a multiple of the number of threads per core (2). Fix Cores per Socket and NUMA nodes in the CPU Topology section in order to use this latency sensitivity option.
$spec.LatencySensitivity = New-Object VMware.Vim.LatencySensitivity
$spec.LatencySensitivity.Level = [VMware.Vim.LatencySensitivitySensitivityLevel]::high
Write-Log "Setting Simulateneous Threads: $($spec.SimultaneousThreads), and latency sensitivity: $($spec.LatencySensitivity.Level)"
$vm.ExtensionData.ReconfigVM($spec)
#Reset VM Resource configuration
$NewCpuReservation = [Math]::Floor($($vmResourceConfig.CpuReservationMhz / $simulatenousThreads))
Write-Log "Setting new VM CPU Resource configuration for $($vm.Name): $NewCpuReservation"
$vmResourceConfig | Set-VMResourceConfiguration -CpuReservationMhz $NewCpuReservation | Out-Null
#Start the VMS
$vm | Start-VM -Confirm:$false | Out-Null
Write-Log "Starting up in the VM: $($vm.Name)"
#Ping the VMs
while (!(Test-Connection -ComputerName $($vm.Name) -Quiet -Count 1 -BufferSize 16))
{
Write-Log "[$(get-date -format u)] Waiting for $($vm.Name) to be reachable"
Start-Sleep -Seconds 30
}
Write-Log "[$(get-date -format u)]$($vm.Name) is reachable:)"
}
else
{
Write-Log "Cannot set VM's Latency Sensitivity to 'High with HT' since the VM's hardware version is: $($hardwareVersion)"
}
}
Other Custom Scripts
Additional custom PowerShell scripts can be used to configure specific settings inside the deployed DataCore SANsymphony virtual machines. These scripts are executed automatically by the DataCore Installation Manager for vSphere at the end of the deployment process. These scripts must be placed in the appropriate sub folder (CustomScripts\GuestOS) before running the deployment to ensure they are executed correctly.
-
To create a new administrative user in the DataCore SANsymphony virtual machine, place the dimv-CreateUserSSY.ps1 script in the CustomScripts\GuestOS folder.
Copy<#
Create a local user with administrative privileges in SANsymphony
and disable RDP allowance for this user
(on every guest OS this user must be created, but on SANsymphony the user will be registered just once in a group)
#>
#Creds: CHANGE THESE SETTINGS WHEN NEEDED
$User = "LocalAdmin"
$Pass = "AdminPassword123"
net user $User $Pass /add /expires:never
#net localgroup administrators $User /add
Write-Host "Successfully added local user $($User)"
#Remove RDP access for a particular user.
# Define the policy name
$denyPolicy = "Deny logon through Remote Desktop Services"
# Get the SID for the user
$userSID = (New-Object System.Security.Principal.NTAccount($User)).Translate([System.Security.Principal.SecurityIdentifier]).Value
# Set the policy
secedit /export /cfg "$env:Temp\secpol.cfg"
(Get-Content "$env:Temp\secpol.cfg") -replace "($denyPolicy\s*=)", "`$1 $userSID" | Set-Content "$env:Temp\secpol.cfg"
secedit /configure /db secedit.sdb /cfg "$env:Temp\secpol.cfg" /areas USER_RIGHTS
Write-Output "RDP access has been denied for $User."
#register Cmdlets.
$bpKey = 'BaseProductKey'
$regKey = Get-Item "HKLM:\Software\DataCore\PowershellSupport"
$installPath = $regKey.getValue('InstallPath')
Import-Module "$installPath\DataCore.Executive.Cmdlets.dll" -DisableNameChecking -ErrorAction Stop
Write-Host "Successfully registered Cmdlets for Windows PowerShell."
#SSY cmds
Connect-DcsServer
$dcsUser = Get-DcsUser -User $User
if ($dcsUser -eq $null)
{
Add-DcsUser -Name $User
Add-DcsUserRole -User $User -Role "Full Privileges"
Write-Host "Successfully added user $($User) to SSY users with Full Privileges."
} -
To configure the Network Time Protocol (NTP) settings to ensure time synchronization within the DataCore SANsymphony virtual machine, place the dimv-GuestOSTimeSource-pool-ntp-org.ps1 script in the CustomScripts\GuestOS folder.
#Set a time source and change the default settings about when a sync should take place to 60 minutes.
# Sets the NTP server
#CHANGE THESE SETTINGS WHEN NEEDED
$NtpServer = "pool.ntp.org,0x1" # Replace with your desired NTP server
w32tm /config /manualpeerlist:$NtpServer /syncfromflags:manual /reliable:YES /update
# Set the synchronization interval to 60 minutes (3600 seconds)
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient" -Name "SpecialPollInterval" -Value 3600
# Restart the Windows Time service to apply changes
Restart-Service w32time
# Force synchronization to verify
w32tm /resync