As the next part of the little mini-series on automating Host Profiles in PowerCLI is a problem I came up against, and based on the Google results I think a lot of others have as well.  As in this blog post by Kyle Gleed on the VMware Blogs.  The default setting in a host Profile will prompt the user for a MAC address for any vmKernel ports being created when applying the profile. This works fine when applying the profile in the GUI as clicking next on the prompt without supplying a MAC address will force vCenter to generate a MAC on its own and use that.  However if you do the same with PowerCLI, the host profile will not apply until an answer is supplied for each MAC address.

There is a simple work around for this, which is to edit the host profile and change the policy on each vmKernel port being created from the default “Determine how MAC address for vmknic should be decided” to “User must explicitly choose the policy option“.  With the host profile configured in this way the MAC addresses will now be generated automatically in the same way they would have been doing it through the GUI.

The problem I have with this workaround is if the profile is updated from the reference host all these settings are reverted to default again and will prompt for the MAC address and will need to be changed again for every vmKernel port in the profile.  I prefer to update the host profile before I use it to ensure I have the latest version of the config, as I work in an environment with a fairly high rate of change and we make heavy use of vmKernel ports for keeping NFS storage traffic separated.  To improve this I have automated the process of changing these policy settings.

So the first step is to retrieve the host profile we want to prepare for use with PowerCLI

$Profile = Get-VMHostProfile -Name $HostProfile

Next we need to use the vSphere APIs to create a profile customization spec, this is essentially a host profile secification we can edit and then write back to the original host profile.

$Spec = New-Object VMware.Vim.HostProfileCompleteConfigSpec

What we need to be able to do now is copy the configuration from our Host Profile in to our customization spec, for this I have used the Copy-Property function by Dennis Verwiej as there is no need to reinvent the wheel here.

Copy-Property -From $Profile.ExtensionData.Config -To $Spec

Now we have a customization spec that is a copy of our original host profile, we can now make the changes we need within the spec.

IF (($Profile.ExtensionData.Config.ApplyProfile.Network.DvsHostNic))
	{
	FOREACH ($Policy in $Spec.ApplyProfile.Network.DvsHostNic)
	    {
	    ($Policy.Policy | Where {$_.Id -like "MacAddressPolicy"}).PolicyOption.Id = "NoDefaultOption"
	    }
	}

First off this is testing to see if there are any DvsHostNic or vmKernel ports attached to a distributed virtual switch, if there is it will then foreach through each NIC and change the policy to “;NoDefaultOption”;.  We can now go through and do the same for any vmKernel ports attached to virtual standard switches.

IF (($Profile.ExtensionData.Config.ApplyProfile.Network.HostPortGroup))
	{
	FOREACH ($Policy in $Spec.ApplyProfile.Network.HostPortGroup)
	    {
	    ($Policy.Policy | Where {$_.Id -like "MacAddressPolicy"}).PolicyOption.Id = "NoDefaultOption"
	    }
	}

Now all the settings should be correct for the vmKernel ports to not prompt for a MAC address, I also like to remove the settings from the profile to join the host to domain as this is far easier to manage with the  Set-VMHostAuthenticationCommand.

IF (($Profile.ExtensionData.Config.ApplyProfile.Authentication.ActiveDirectory.Policy[0].PolicyOption.ID) -eq "FixedJoinedDomainOption")
	{
	($Spec.ApplyProfile.Authentication.ActiveDirectory.Policy | Where {$_.Id -eq "JoinedDomainPolicy"}).PolicyOption.ID = "DomainNotSetOption"
	}

Similarly to the method for changing the MAC address policies, this sections is first checking if the policy is set to perform a domain join, and then if it is, it will change the policy to “;DomainNotSetOption”;.

Finally now we have the policies all set how we want them to interact correctly with PowerCLI we can write our customization spec back to the Host Profile.

$Profile.ExtensionData.UpdateHostProfile($Spec)

Using this as part of an automation process it is now simple to be able to Update a Host Profile from Reference Host  and then prepare the profile for use with PowerCLI.

$Profile = Get-VMHostProfile -Name $HostProfile

$Spec = New-Object VMware.Vim.HostProfileCompleteConfigSpec

Copy-Property -From $Profile.ExtensionData.Config -To $Spec

IF (($Profile.ExtensionData.Config.ApplyProfile.Network.DvsHostNic))
    {
    FOREACH ($Policy in $Spec.ApplyProfile.Network.DvsHostNic)
        {
        ($Policy.Policy | Where {$_.Id -like "MacAddressPolicy"}).PolicyOption.Id = "NoDefaultOption"
        }
    }

IF (($Profile.ExtensionData.Config.ApplyProfile.Network.HostPortGroup))
    {
    FOREACH ($Policy in $Spec.ApplyProfile.Network.HostPortGroup)
        {
        ($Policy.Policy | Where {$_.Id -like "MacAddressPolicy"}).PolicyOption.Id = "NoDefaultOption"
        }
    }

IF (($Profile.ExtensionData.Config.ApplyProfile.Authentication.ActiveDirectory.Policy[0].PolicyOption.ID) -eq "FixedJoinedDomainOption")
    {
    ($Spec.ApplyProfile.Authentication.ActiveDirectory.Policy | Where {$_.Id -eq "JoinedDomainPolicy"}).PolicyOption.ID = "DomainNotSetOption"
    }

$Profile.ExtensionData.UpdateHostProfile($Spec)

Comments