VMware Cloud Community
taskino
Enthusiast
Enthusiast

Create Host Customization Specs

Hello All,

I am trying understand what it takes to create  host customization answer spec file. I have several fields that are required; 

Based on the Get-VMHostProfileRequiredInput -VMHost $vmhost i have the following required input values; 

network.GenericNetStackInstanceProfile["key-vim-profile-host-GenericNetStackInstanceProfile-defaultTcpipStack"].GenericDnsConfigProfile.HostNamePolicy.hostName
network.dvsHostNic["key-vim-profile-host-DvsHostVnicProfile-dvSwitch-vMotion-VMK-VMotion-B-vmk2"].ipConfig.IpAddressPolicy.address
network.dvsHostNic["key-vim-profile-host-DvsHostVnicProfile-dvSwitch-vMotion-VMK-VMotion-B-vmk2"].ipConfig.IpAddressPolicy.subnetmask
network.dvsHostNic["key-vim-profile-host-DvsHostVnicProfile-dvSwitch-vMotion-VMK-VMotion-A-vmk1"].ipConfig.IpAddressPolicy.subnetmask
network.dvsHostNic["key-vim-profile-host-DvsHostVnicProfile-dvSwitch-vMotion-VMK-VMotion-A-vmk1"].ipConfig.IpAddressPolicy.address
network.hostPortGroup["key-vim-profile-host-HostPortgroupProfile-VMK-Management"].ipConfig.IpAddressPolicy.address
network.hostPortGroup["key-vim-profile-host-HostPortgroupProfile-VMK-Management"].ipConfig.IpAddressPolicy.subnetmask

I have these values in a csv file. HostName, MgmtIP, MgmtSubnet,vMotion1IP, vMotion1Subnet,vMotion2IP,vMotion2SubnetMask etc

I am trying to understand how to create value key pair for each one of the item. 

The example core i found here

and here 

has good examples but i am having hard time construct key, value pair for each section. 

sample code;

# Check to see if it already has an answer file
$targethost = 'myhost.abc.local'
$hostProfileManagerView = Get-View "HostProfileManager"
$answerFile = $hostProfileManagerView.RetrieveAnswerFile($targetHost.ExtensionData.MoRef)
if (-not $answerFile) {
# Create an answer file with the IP addresses filled in
$answerFileCreateSpec = New-Object VMware.Vim.AnswerFileOptionsCreateSpec
foreach ($network in $hostNetworks) {
$addr = New-Object VMware.Vim.KeyAnyValue
$addr.key = "address"
$addr.value = $network[1]
$mask = New-Object VMware.Vim.KeyAnyValue
$mask.key = "subnetmask"
$mask.value = $network[2]
$propPath = New-Object VMware.Vim.ProfilePropertyPath
# Fix up the portgroup name (comma becomes underscore, squash spaces)
$propPath.ProfilePath = 'network.hostPortGroup["key-vim-profile-host-HostPortgroupProfile-'+$network[0].Replace(",","_").Replace(" ","")+'"].ipConfig'
$propPath.PolicyId = "IpAddressPolicy"
$param = New-Object VMware.Vim.ProfileDeferredPolicyOptionParameter
$param.InputPath = $propPath
$param.Parameter += $addr
$param.Parameter += $mask
$answerFileCreateSpec.UserInput += $param
}
# Now store the new answer file information
$hostProfileManagerView.UpdateAnswerFile($targetHost.ExtensionData.MoRef, $answerFileCreateSpec)
# Now store the new answer file information
$hostProfileManagerView.UpdateAnswerFile($targetHost.ExtensionData.MoRef, $answerFileCreateSpec)

Write "Added Host $targetHost"
} else {
Write "Host $targetHost already has a valid answer file, skipping."
}

 

can anyone show help me understand how to construct key pair value for each and add to answerfile?

thank you! 

 

 

 

Reply
0 Kudos
17 Replies
LucD
Leadership
Leadership

What is in $network[1] and $network[2]?
Where is $hostNetworks coming from?

I'm not exactly sure what you are asking.
The code you included is just an incomplete copy of the code in that 2nd link


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
taskino
Enthusiast
Enthusiast

sorry LucD that was just a sample code was not full, I modified it came up with the following; does this look OK? especially adding all to array. 

 

# Define Variables
$targethost = 'myhost.abc.local'
$ManagementIP = "Some Value from csv"
$ManagementSubnetMask = "Some Value from csv"
$vMotionAIP = "Some Value from CSV"
$vMotionASubnetMask = "Some Value from CSV"
$vMotionBIP = "Some Value from CSV"
$vMotionBSubnetMask = "Some Value from CSV"
$hostProfileManagerView = Get-View "HostProfileManager"
$answerFile = $hostProfileManagerView.RetrieveAnswerFile($targetHost.ExtensionData.MoRef)

if (-not $answerFile) {
# Create an answer with required values
$answerFileCreateSpec = New-Object VMware.Vim.AnswerFileOptionsCreateSpec
#HostName
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.GenericNetStackInstanceProfile["key-vim-profile-host-GenericNetStackInstanceProfile-defaultTcpipStack"].GenericDnsConfigProfile'
$propPath.PolicyId = "HostNamePolicy"
$hostname = New-Object VMware.Vim.KeyAnyValue
$hostname.key = "Name for this host"
$hostname.value = "$TargetHost"


#Management IP
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.hostPortGroup["key-vim-profile-host-HostPortgroupProfile-VMK-Management"].ipConfig'
$propPath.PolicyId = "IpAddressPolicy"
$maddr = New-Object VMware.Vim.KeyAnyValue
$maddr.key = "Host IPv4 address"
$maddr.value = "$ManagementIP"
$mmask = New-Object VMware.Vim.KeyAnyValue
$mmask.key = "Subnet Mask"
$mmask.value = "$ManagementSubnetMask"
#vMotionA
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.dvsHostNic["key-vim-profile-host-DvsHostVnicProfile-dvSwitch-vMotion-VMK-VMotion-A-vmk1"].ipConfig'
$propPath.PolicyId = "IpAddressPolicy"
$VAaddr = New-Object VMware.Vim.KeyAnyValue
$VAaddr.key = "Host IPv4 address"
$VAaddr.value = "$vMotionAIP"
$VAmask = New-Object VMware.Vim.KeyAnyValue
$VAmask.key = "Subnet Mask"
$VAmask.value = "$vMotionASubnetMask"
#vMotionB
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.dvsHostNic["key-vim-profile-host-DvsHostVnicProfile-dvSwitch-vMotion-VMK-VMotion-B-vmk2"].ipConfig'
$propPath.PolicyId = "IpAddressPolicy"
$VBaddr = New-Object VMware.Vim.KeyAnyValue
$VBaddr.key = "Host IPv4 address"
$VBaddr.value = "$vMotionBIP"
$VBmask = New-Object VMware.Vim.KeyAnyValue
$VBmask.key = "Subnet Mask"
$VBmask.value = "$vMotionBSubnetMask"


$param = New-Object VMware.Vim.ProfileDeferredPolicyOptionParameter
$param.InputPath = $propPath
$param.Parameter += $HostName
$param.Parameter += $maddr
$param.Parameter += $mmask
$param.Parameter += $VAaddr
$param.Parameter += $VAmask
$param.Parameter += $VBaddr
$param.Parameter += $VBmask
$answerFileCreateSpec.UserInput += $param


}
# Now store the new answer file information
$hostProfileManagerView.UpdateAnswerFile($targetHost.ExtensionData.MoRef, $answerFileCreateSpec)
Write "Added Host $targetHost"
} else {
Write "Host $targetHost already has a valid answer file, skipping."
}

 

Thank you! 

Reply
0 Kudos
LucD
Leadership
Leadership

Ok, besides that $targetHost should be an object instead of a String

$targethost = Get-VMHost -Name 'myhost.abc.local'

 and an out of place curly brace
This

}
# Now store the new answer file information


should be

# Now store the new answer file information

This all looks ok to me.
So it is still not clear to me what the actual question is?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
taskino
Enthusiast
Enthusiast

sorry LucD, i just was not sure how to make the array correctly but i got that part. Now i have  a follow up question if you don't mind. I am getting the following error and could not decode it yet; 

"exception calling "UpdateAnswerFile" with "2" argument(s): "The object 'vim.HostSystem:host-1465' has already been deleted or has not been completely created"
At line:84 char:3
+ $hostProfileManagerView.UpdateAnswerFile($targetHost.Extensio ...
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : VimException"

Here is the latest script; 

#Disconnect-VIserver * -confirm:$false
Connect-VIServer -Server "svcenter1.abc.local"
#Host Information
$csv = import-Csv -Path "D:\Deploy\AnswerFileTest.csv"

$Hostlist = $csv

ForEach ($VMHost in $Hostlist) {

$CurrentHost = $VMHost.ESXIHostName
$Esxishortname = $VMHost.ESXIHostName.split(".")[0]
$CurrentHostIP = $VMHost.ManagementIP
$ManagementIP = $VMHost.ManagementIP
$ManagementSubnetMask= $VMHost.ManagementSubnetMask
$vMotionAIP = "$VMHost.VMK-vMotion-AIP"
$vMotionASubnetMask = "$VMHost.VMK-vMotion-ASubnetMask"
$vMotionBIP = "$VMHost.VMK-vMotion-BIP"
$vMotionBSubnetMask = "$VMHost.VMK-vMotion-BSubnetMask"

# Define Variables
$targethost = Get-VMHost -Name $CurrentHost

$hostProfileManagerView = Get-View "HostProfileManager"
#Create an answer file with the IP addresses filled in
$answerFileCreateSpec = New-Object VMware.Vim.AnswerFileOptionsCreateSpec
#HostName
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.GenericNetStackInstanceProfile["key-vim-profile-host-GenericNetStackInstanceProfile-defaultTcpipStack"].GenericDnsConfigProfile'
$propPath.PolicyId = "HostNamePolicy"
$hostname = New-Object VMware.Vim.KeyAnyValue
$hostname.key = "hostName"
$hostname.value = "$Esxishortname"


#Management IP
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.hostPortGroup["key-vim-profile-host-HostPortgroupProfile-VMK-MGT"].ipConfig'
$propPath.PolicyId = "IpAddressPolicy"
$maddr = New-Object VMware.Vim.KeyAnyValue
$maddr.key = "address"
$maddr.value = "$ManagementIP"
$mmask = New-Object VMware.Vim.KeyAnyValue
$mmask.key = "subnetmask"
$mmask.value = "$ManagementSubnetMask"
#vMotionA
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.dvsHostNic["key-vim-profile-host-DvsHostVnicProfile-dvSwitch-vMotion-VMK-VMotion-A-vmk1"].ipConfig'
$propPath.PolicyId = "IpAddressPolicy"
$VAaddr = New-Object VMware.Vim.KeyAnyValue
$VAaddr.key = "address"
$VAaddr.value = "$vMotionAIP"
$VAmask = New-Object VMware.Vim.KeyAnyValue
$VAmask.key = "subnetmask"
$VAmask.value = "$vMotionASubnetMask"
#vMotionB
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.dvsHostNic["key-vim-profile-host-DvsHostVnicProfile-dvSwitch-vMotion-VMK-VMotion-B-vmk2"].ipConfig'
$propPath.PolicyId = "IpAddressPolicy"
$VBaddr = New-Object VMware.Vim.KeyAnyValue
$VBaddr.key = "address"
$VBaddr.value = "$vMotionBIP"
$VBmask = New-Object VMware.Vim.KeyAnyValue
$VBmask.key = "subnetmask"
$VBmask.value = "$vMotionBSubnetMask"


$param = New-Object VMware.Vim.ProfileDeferredPolicyOptionParameter
$param.InputPath = $propPath
$param.Parameter += $HostName
$param.Parameter += $maddr
$param.Parameter += $mmask
$param.Parameter += $VAaddr
$param.Parameter += $VAmask
$param.Parameter += $VBaddr
$param.Parameter += $VBmask
$answerFileCreateSpec.UserInput += $param




# Now store the new answer file information
$hostProfileManagerView.UpdateAnswerFile($targetHost.ExtensionData.MoRef, $answerFileCreateSpec)

Write "Added Host $targetHost"

}

 

Also i am attaching a code capture as well from vCenter.  I updated host customization spec while capturing code. Perhaps that may shed some clues about the error i am getting above. 

Thank you. 

Reply
0 Kudos
LucD
Leadership
Leadership

Did you stop/start your PS session before running the script?
That error often occurs when there is some corruption in the PS session.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Tags (1)
Reply
0 Kudos
taskino
Enthusiast
Enthusiast

thank you. I was running in PowerShell ISE had multiple tabs.  Now getting different error. Seems like does not like host value passing on into

$hostProfileManagerView.UpdateAnswerFile($targetHost.ExtensionData.MoRef, $answerFileCreateSpec)

 

Cannot convert argument "host", with value: "System.Object[]", for "UpdateAnswerFile" to type "VMware.Vim.ManagedObjectReference": "Cannot convert the "System.Object[]" value of type
"System.Object[]" to type "VMware.Vim.ManagedObjectReference"."
At line:64 char:1
+ $hostProfileManagerView.UpdateAnswerFile($targetHost.ExtensionData.Mo ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

 

Thank you! 

Reply
0 Kudos
LucD
Leadership
Leadership

Looks like you have more than 1 object in $targetHost.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
taskino
Enthusiast
Enthusiast

thank you for your patience. Closed all the PS windows and started again. I am not getting error currently which is great. I can see Host Customization is being updated in the vCenter and completes successfully.  When i looked at the host in the vCenter i don't see  the values set. I am not seeing property name and values in the host customization. 

i am attaching two screenshots working (done manually) vs the one i am trying update with script. 

What level of troubleshooting can i do further? 

Thank you!

 

Reply
0 Kudos
taskino
Enthusiast
Enthusiast

OK, it seems like something wrong with the array itself values are not passing correctly or key value pairs 

PS C:\Users\abcuser>$param
InputPath Parameter
--------- ---------
VMware.Vim.ProfilePropertyPath {hostName, address, subnetmask, address...}

PS C:\Users\abcuser>$param.parameter

Key Value
--- -----
hostName myesxi.abc.com
address 10.20.30.49
subnetmask 255.255.255.128
address @{ESXIHostName=myesxi.abc.com.; Scratch=/vmfs/volumes/5db0bea0-11723efe-52ee-062a35100fe9/scratch-myesxi.abc.com; ManagementName=vmk0; ManagementIP=10.20.30.49; M
subnetmask @{ESXIHostName=myesxi.abc.com.; Scratch=/vmfs/volumes/5db0bea0-11723efe-52ee-062a35100fe9/scratch-myesxi.abc.com; ManagementName=vmk0; ManagementIP=10.20.30.49; M
address @{ESXIHostName=myesxi.abc.com.; Scratch=/vmfs/volumes/5db0bea0-11723efe-52ee-062a35100fe9/scratch-myesxi.abc.com; ManagementName=vmk0; ManagementIP=10.20.30.49; M
subnetmask @{ESXIHostName=myesxi.abc.com.; Scratch=/vmfs/volumes/5db0bea0-11723efe-52ee-062a35100fe9/scratch-myesxi.abc.com; ManagementName=vmk0; ManagementIP=10.20.30.49; M

 

Reply
0 Kudos
taskino
Enthusiast
Enthusiast

more progress had a bad variable names (it has - in it ) now i can get the csv values correctly but host is still not updating as expected. I wonder if it is due to multiple same key value names that it does not know where to update it. 

PS C:\Users\abcuser> $param.parameter

Key Value
--- -----
hostName myesxi.abc.com
address 10.20.30.49
subnetmask 255.255.255.128
address 10.20.31.137
subnetmask 255.255.255.0
address 10.20.31.138
subnetmask 255.255.255.0

 

 

Reply
0 Kudos
LucD
Leadership
Leadership

Can you attach a version of the current script you are using?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
taskino
Enthusiast
Enthusiast

Here is the latest script:

#Disconnect-VIserver * -confirm:$false
Connect-VIServer -Server "svcenter1.abc.local"
#Host Information
$csv = import-Csv -Path "D:\Deploy\AnswerFileTest.csv"

$Hostlist = $csv

ForEach ($VMHost in $Hostlist) {

$CurrentHost = $VMHost.ESXIHostName
$Esxishortname = $VMHost.ESXIHostName.split(".")[0]
$CurrentHostIP = $VMHost.ManagementIP
$ManagementIP = $VMHost.ManagementIP
$ManagementSubnetMask= $VMHost.ManagementSubnetMask
$vMotionAIP = $VMHost.VMKvMotionAIP
$vMotionASubnetMask = $VMHost.VMKvMotionASubnetMask
$vMotionBIP = $VMHost.VMKvMotionBIP
$vMotionBSubnetMask = $VMHost.VMKvMotionBSubnetMask

# Define Variables
$targethost = Get-VMHost -Name $CurrentHost

$hostProfileManagerView = Get-View "HostProfileManager"
#Create an answer file with the IP addresses filled in
$answerFileCreateSpec = New-Object VMware.Vim.AnswerFileOptionsCreateSpec
#HostName
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.GenericNetStackInstanceProfile["key-vim-profile-host-GenericNetStackInstanceProfile-defaultTcpipStack"].GenericDnsConfigProfile'
$propPath.PolicyId = "HostNamePolicy"
$hostname = New-Object VMware.Vim.KeyAnyValue
$hostname.key = "hostName"
$hostname.value = "$Esxishortname"


#Management IP
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.hostPortGroup["key-vim-profile-host-HostPortgroupProfile-VMK-MGT"].ipConfig'
$propPath.PolicyId = "IpAddressPolicy"
$maddr = New-Object VMware.Vim.KeyAnyValue
$maddr.key = "address"
$maddr.value = "$ManagementIP"
$mmask = New-Object VMware.Vim.KeyAnyValue
$mmask.key = "subnetmask"
$mmask.value = "$ManagementSubnetMask"

#vMotionA
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.dvsHostNic["key-vim-profile-host-DvsHostVnicProfile-dvSwitch-vMotion-VMK-VMotion-A-vmk1"].ipConfig'
$propPath.PolicyId = "IpAddressPolicy"
$VAaddr = New-Object VMware.Vim.KeyAnyValue
$VAaddr.key = "address"
$VAaddr.value = "$vMotionAIP"
$VAmask = New-Object VMware.Vim.KeyAnyValue
$VAmask.key = "subnetmask"
$VAmask.value = "$vMotionASubnetMask"

#vMotionB
$propPath = New-Object VMware.Vim.ProfilePropertyPath
$propPath.ProfilePath = 'network.dvsHostNic["key-vim-profile-host-DvsHostVnicProfile-dvSwitch-vMotion-VMK-VMotion-B-vmk2"].ipConfig'
$propPath.PolicyId = "IpAddressPolicy"
$VBaddr = New-Object VMware.Vim.KeyAnyValue
$VBaddr.key = "address"
$VBaddr.value = "$vMotionBIP"
$VBmask = New-Object VMware.Vim.KeyAnyValue
$VBmask.key = "subnetmask"
$VBmask.value = "$vMotionBSubnetMask"


$param = New-Object VMware.Vim.ProfileDeferredPolicyOptionParameter
$param.InputPath = $propPath
$param.Parameter += $HostName
$param.Parameter += $maddr
$param.Parameter += $mmask
$param.Parameter += $VAaddr
$param.Parameter += $VAmask
$param.Parameter += $VBaddr
$param.Parameter += $VBmask
$answerFileCreateSpec.UserInput += $param

#Now store the new answer file information
$hostProfileManagerView.UpdateAnswerFile($targetHost.ExtensionData.MoRef, $answerFileCreateSpec)

Write "Added Host $targetHost"

}

 

When i looked the code capture i noticed that it adds the following for each section. I am attaching code capture output as well. 

New-Object VMware.Vim.ProfileDeferredPolicyOptionParameter

 

Thank you! 

Reply
0 Kudos
LucD
Leadership
Leadership

The answer file created by that script seems to be ok (I ran CheckAnswerFileStatus).

That Code Capture is when the ConfigSpec is created, that is after the Answer file is created.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
taskino
Enthusiast
Enthusiast

it is weird, when i reset the host customization specs  i see all the fields (around 10) that needs an input (screenshot1)  then i run the script to set the field values it gets trimmed down to only 4 fields which already populated itself after host customization reset. (screenshot2) 

Wondering if there is a better way accomplish this?  Do you have any suggestions? how can I troubleshoot this further and make it work? 

Thank you! 

 

 

Reply
0 Kudos
LucD
Leadership
Leadership

To be honest, I stopped using HostProfiles several years ago.
I found it cumbersome and unreliable.
Could be me of course.

There are some alternatives.

Script your changes (the method I use most of the time).
Since you already have a CSV with all the data, you can use the script for all your ESXi nodes.

Use DSC.
With the vSphereDSC module there are many settings that can be done this way.
Since the future of DSC in general (MSFT) and the vSphereDSC module itself is currently uncertain, it is a bit of a gamble to invest in DSC.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
taskino
Enthusiast
Enthusiast

Understood. Thank you for the help! I appreciate it. 

Reply
0 Kudos
parmarnandish
Contributor
Contributor

Hi @taskino, were you able to make this work? I am trying to do something similar on vsphere 7. I need to use auto-deploy and prepopulate the host customizations for the hosts that I want to add. 

Reply
0 Kudos