You can use the first disk argument only to specify the search order. You cannot explicitly specify a disk. For example, you cannot specify a specific LUN on a SAN.
When configuring a System Image Install disk, you have multiple options to define the device you want ESXi to be installed to and booted from. You can use the following arguments to define the disk for the installation:
- esx – The first disk detected containing a valid installation of ESXi
- local – The first local disk detected by ESXi after boot
- device model
- device vendor
- vmkernel device driver name
There is the undocumented argument remote. In a Kickstart-script you can use the argument remote to install ESXi on a remote disk and boot from SAN. You can do the same way for vSphere Auto Deploy. The ESXi Host has an array of remote disks. If there are more than one remote disks, it write the installation to the first remote disk detected by ESXi. Make sure, that the ESXi Host has only one unformated and unused remote disk.
Configure the Host Profile for Stateful Installation under Advanced Configuration Settings > System Image Cache Configuration > System Image Cache Configuration.
- In the System Image Cache Profile Settings drop-down menu, choose the policy option Enable stateful installs on the host.
- Specify information about the disk to use Arguments for first disk and set it to remote.
- Leave the Option Check to overwrite any VMFS volumes on the selected disk unchecked (thats because the Host Profile will write the installation to the first unused remote disk)
Three steps are recomended: Auto Deploy ESXi in a Cluster, Stateful Auto Deploy, and Post Auto Deploy. This steps can be executed with a PowerShell-Script (PCLI workflow).
Execute Auto Deploy. Boot the Host in to PXE and let Auto Deploy do the rest for you ... This step should only do the deployment in memory and adding the ESXi Host to a Cluster - nothing else.
sequenceDiagram
participant PCLI workflow
participant DHCP
participant TFTP
participant ESXi
participant Auto Deploy
participant Deploy Rule
PCLI workflow->>ESXi: OneTimePXE boot
ESXi->>DHCP: Give me my IP and TFTP options
DHCP->>ESXi: Your IP and TFTP options are ...
ESXi->>TFTP: Give me my Auto Deploy Server
TFTP->>ESXi: Your Auto Deploy Server is ...
ESXi->>Auto Deploy: Connect and start Installation
Auto Deploy->>Deploy Rule: Give me my deployment rules
Deploy Rule->>Auto Deploy: Image Profile ...
Deploy Rule->>Auto Deploy: Cluster ...
Auto Deploy->>ESXi: Install ESXi in memory
Auto Deploy->>ESXi: Add Host to the Cluster
This step should do the Stateful installs. Its necessaire, that you make sure there is no unformated storage attached to the new Host before remediate Stateful Profile. If there are more than one unformated disks attached, it can be that ESXi detect the wrong disk an write the ESXi installation to this!
sequenceDiagram
participant PCLI workflow
participant ESXi
participant Stateful Profile
PCLI workflow->>ESXi: Check for unformated remote storage (needs to be coded)
loop Format-SanStorage
ESXi->>ESXi: Format unformated storage with VMFS (needs to be coded)
end
PCLI workflow->>ESXi: Attach Stateful Profile
Stateful Profile->>ESXi: Enable stateful installs on the host: remote
Stateful Profile->>ESXi: Remediate
ESXi->>PCLI workflow: Return
PCLI workflow->>ESXi: Restart Host
Make all of your post actions here. Switch the Stateful Host Profile to the final Host Profile and reboot the ESXi Host.
sequenceDiagram
participant PCLI workflow
participant ESXi
participant Final Profile
PCLI workflow->>ESXi: Add License to Host
PCLI workflow->>ESXi: Change Host Profile
ESXi->>Final Profile: Attach Host Profile
ESXi->>Final Profile: Attach Host Customization
Final Profile->>ESXi: Remediate
ESXi->>PCLI workflow: Return
PCLI workflow->>ESXi: Restart Host
With this configuration, I hope all of my ESXi installations are going well.
Run the esxcli storage filesystem list
command to generate a compact list of the LUNs currently connected to the ESXi host, including VMFS version.
function Get-IXESXiLuns {
[CmdletBinding()]
param(
#region parameter, to add a new parameter, copy and paste the Parameter-region
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
Position = 0
)]
[Object] $InputObject
#endregion
)
begin{
#region Do not change this region
$StartTime = Get-Date
$function = $($MyInvocation.MyCommand.Name)
Write-Verbose $('[', (Get-Date -f 'yyyy-MM-dd HH:mm:ss.fff'), ']', '[ Begin ]', $function -Join ' ')
#endregion
$ret = $null # or @()
}
process{
Write-Verbose $('[', (Get-Date -f 'yyyy-MM-dd HH:mm:ss.fff'), ']', '[ Process ]', $function -Join ' ')
try{
$ret = foreach($item in $InputObject.EsxiServer){
#Esxi server information
$esxi = Get-VMhost $item
Write-Verbose "Rescan/Refresh Esxi Storage on $($item)"
try{
$null = $esxi | Get-VMHostStorage -Refresh -RescanAllHba -ErrorAction Stop
}catch{
Write-Warning $('ScriptName:', $($_.InvocationInfo.ScriptName), 'LineNumber:', $($_.InvocationInfo.ScriptLineNumber), 'Message:', $(($_.Exception.Message) -replace '\s+',' ') -Join ' ')
$Error.Clear()
}
Write-Verbose "Get HBA storage adapter information on $($item)"
$hostHBA = $esxi | Get-VMHostHba | Where-Object {$_.Status -match 'online'}
#Get the list of Datastore
$datastore = Get-Datastore
Write-Verbose "Get available LUN storage devices list on $($item)"
$lunList = $hostHBA | Get-ScsiLun
#Get the list of LUN on datastores are created
Write-Verbose "Get the list of LUN on datastores are created on $($item)"
foreach ($lun in $lunList){
$DatastoreName = @{N='DatastoreName'; E={$datastore | Where-Object {$_.Extensiondata.Info.Vmfs.Extent.DiskName.Contains($lun.CanonicalName)} | Select-Object -ExpandProperty Name}}
$AttachedLun = $lun | Select-Object VMHost, CanonicalName, RuntimeName, CapacityGB, $DatastoreName
if([String]::IsNullOrEmpty($AttachedLun.DatastoreName)){
if($InputObject.Formatted -eq $false){
if($AttachedLun.CapacityGB -ne 100){
$CN = $AttachedLun.RuntimeName -split ':'
$LunID = $($CN[$CN.GetUpperBound(0)]).Trim('L')
Write-Verbose "$($AttachedLun.VMHost): $($AttachedLun.CanonicalName) $($AttachedLun.RuntimeName) is not VMFS-formated"
switch -Regex ($AttachedLun.VMHost){
'\w\w\w\w60\d{2}' { $NewDatastoreName = "G_$($InputObject.ESxiCluster)_G_VMFS_$($LunID)" }
'\w\w\w\w90\d{2}' { $NewDatastoreName = "S_$($InputObject.ESxiCluster)_S_VMFS_$($LunID)" }
}
$AttachedLun | Add-Member -MemberType NoteProperty -Name NewDatastoreName -Value $NewDatastoreName
$AttachedLun
}
}
}else{
if($InputObject.Formatted){
$AttachedLun
}
}
}
}
}catch{
Write-Warning $('ScriptName:', $($_.InvocationInfo.ScriptName), 'LineNumber:', $($_.InvocationInfo.ScriptLineNumber), 'Message:', $(($_.Exception.Message) -replace '\s+',' ') -Join ' ')
$Error.Clear()
}
}
end{
#region Do not change this region
Write-Verbose $('[', (Get-Date -f 'yyyy-MM-dd HH:mm:ss.fff'), ']', '[ End ]', $function -Join ' ')
$TimeSpan = New-TimeSpan -Start $StartTime -End (Get-Date)
$Formatted = $TimeSpan | ForEach-Object {
'{1:0}h {2:0}m {3:0}s {4:000}ms' -f $_.Days, $_.Hours, $_.Minutes, $_.Seconds, $_.Milliseconds
}
Write-Verbose $('Finished in:', $Formatted -Join ' ')
#endregion
return $ret
}
}
cls
Write-Host "List all formatted LUNS of MyHost.comapny.ch" -ForegroundColor Green
$ret = Get-IXESXiLuns -InputObject @{EsxiServer = 'MyHost.comapny.ch'; Formatted = $true; ESxiCluster = 'MyCluster'}
$ret | Format-Table -AutoSize
function Format-IXESXiLuns {
[CmdletBinding()]
param(
#region parameter, to add a new parameter, copy and paste the Parameter-region
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
Position = 0
)]
[Object] $InputObject
#endregion
)
begin{
#region Do not change this region
$StartTime = Get-Date
$function = $($MyInvocation.MyCommand.Name)
Write-Verbose $('[', (Get-Date -f 'yyyy-MM-dd HH:mm:ss.fff'), ']', '[ Begin ]', $function -Join ' ')
#endregion
$ret = $null # or @()
}
process{
Write-Verbose $('[', (Get-Date -f 'yyyy-MM-dd HH:mm:ss.fff'), ']', '[ Process ]', $function -Join ' ')
try{
Write-Verbose "Add new Datastore using RuntimeName of newly Added Lun"
$ret = foreach($item in $InputObject){
Write-Verbose "Datastore: $($item.NewDatastoreName), Path: $($item.CanonicalName)"
New-Datastore -VMHost $item.VMHost -Name $item.NewDatastoreName -Path $item.CanonicalName -Vmfs -FileSystemVersion 6
}
}catch{
Write-Warning $('ScriptName:', $($_.InvocationInfo.ScriptName), 'LineNumber:', $($_.InvocationInfo.ScriptLineNumber), 'Message:', $(($_.Exception.Message) -replace '\s+',' ') -Join ' ')
$Error.Clear()
}
}
end{
#region Do not change this region
Write-Verbose $('[', (Get-Date -f 'yyyy-MM-dd HH:mm:ss.fff'), ']', '[ End ]', $function -Join ' ')
$TimeSpan = New-TimeSpan -Start $StartTime -End (Get-Date)
$Formatted = $TimeSpan | ForEach-Object {
'{1:0}h {2:0}m {3:0}s {4:000}ms' -f $_.Days, $_.Hours, $_.Minutes, $_.Seconds, $_.Milliseconds
}
Write-Verbose $('Finished in:', $Formatted -Join ' ')
#endregion
return $ret
}
}
cls
Write-Host "Format all unformatted LUNS on ESXi Host MyHost.comapny.ch" -ForegroundColor Green
$ret = Format-IXESXiLuns -InputObject $ret -Verbose
$ret | Format-Table -AutoSize
VMware: Configure a Host Profile to Enable Stateful Installs
VMware: Installation and Upgrade Script Commands
VMware: Identifying disks when working with VMware ESXi
Virtual Geek: Add a VMFS datastore using VMware PowerCLI
Tags: #VMware, #ESXi, #AutoDeploy