My biggest annoyance in having multiple vCenters that aren’t in Enhanced Linked Mode is having to do the same task over and over again against different targets. Luckily, PowerCLI and I have become friends over the past few months, and it’s quite good at repetitive tasks. Today, we’ll be using it to clone a role from one vCenter to one or many others.

Thanks to an awesome community, I quickly found a blog post on how to clone a role from one vCenter to another. Grzegorz wrote a great article showing the cmdlets and structure in play to do a 1:1 copy; including the initial creation of the role on the destination vCenter, then matching the privileges included. This would have been everything I needed if my task was just on two vCenters. But it wasn’t. It was on ten vCenters. Foreach loop anyone?

I’m not going to repeat the lessons Grzegorz taught me in his blog post, I’ll let you go there and read it first hand. Instead, I’ll show you how I modified what he wrote to work against one or many destination vCenter servers.

Initially I just planned to create variables that would store the source and destination vCenters, then use a foreach loop to roll through the destination variable and perform the clone. However, I knew that was the cheap and easy way out and wouldn’t be as good as it should be. To be more useful, I’m going to use the global variable ‘$global:DefaultVIServers’ and some input from the user to build out those variables. This script and that global variable are dependant on your session already being connected to all of the vCenter servers you are working with (source and destination), so let’s first show you what you’re connected to:

Disclaimer: I like green.

Write-Host -ForegroundColor Green  'Currently connected vCenter servers:'
$global:DefaultVIServers | Out-Host

Now that the user has a list to pick (and copy) from, let’s ask what the source vCenter is and store the result:

$sourcevc = Read-Host -Prompt 'Input the source vCenter server'
Write-Host -ForegroundColor Green  "Source vCenter server:"
$sourcevc | Out-Host

Now that we have the source, we can set the remaining vCenters as destinations and display them to the user:
This was the only part that tripped me up, as Powershell arrays cannot be subtracted from, but array lists can.

[System.Collections.ArrayList]$destvcs = $global:DefaultVIServers.Name
$destvcs.Remove("$sourcevc")
Write-Host -ForegroundColor Green  "Destination vCenter servers:"
$destvcs | Out-Host

Equipped with that info, let’s make sure they didn’t make a mistake and actually want to proceed:

Read-Host -Prompt "Press Enter to continue or CTRL+C to quit" 

OK, we’re proceeding. Now we list all of the roles on the source vCenter and ask the user which we will be cloning and store that as well:

Write-Host "Roles on $sourcevc" 
Get-VIRole -Server $sourcevc
$role = Read-Host -Prompt 'Input the role to clone'
Get-VIRole -Server $sourcevc -Name $role | fl

Now we’ve got all the info we need from the user, let’s pull a bit more from the source before we start cloning:

[string[]]$privsforRoleFromSource=Get-VIPrivilege -Role (Get-VIRole -Name $role -server $sourcevc) |%{$_.id}
Write-Host -ForegroundColor Green  "Setting the following privileges in $role on $destvcs"
$privsforRoleFromSource | Out-Host

Whew, ok, variable population done! Let’s start cloning:

foreach ($destvc in $destvcs) {
    New-VIRole -Server $destvc -Name $role
    Set-VIRole -Role (Get-VIRole -Name $role -Server $destvc) -AddPrivilege (Get-VIPrivilege -id $privsforRoleFromSource -server $destvc)
}

You can find this whole script as well as other helpful bits of code in Sheetz IT’s public GitHub.

-Willie