In Part1 of this article we had all the roles and permissions exported to an XML file. It’s now time to import the roles and permissions into a Virtual Center.
The script does in fact the reverse of what the script in Part 1 did.
But there were a few “gotchas“ that had to be solved before arriving at a working solution.
Duplicate Names
The script does not take into account that you can have different objects in your vSphere environment with the same name! Which imho is not a good practice in any case.
Should someone have the need for this functionality let me know and I will try to adapt the scripts.
Principals
The script does not create the principals that are mentioned in the XML file. If these principals do not exists in the environment where you want to import the roles and permissions the script will show errors.
Speed of execution
The permissions are set with an API called SetEntityPermissions.
As can be seen in the API Reference Guide this method requires a Managed Object Reference (MoRef) to a ManagedEntity. A ManagedEntity object is the parent object of most of the managed objects in vSphere.
This way of working avoids that there would have to be a separate method for each of the derived managed objects.
In the XML we have the name of the vSphere entity in property $_.Entity. We could get at the required ManagedEntity MoRef like this:
001
|
(Get-Inventory -Name $_.Entity | Get-View).MoRef
|
But if you run this you will notice that this is in fact quite slow. If you need to import hundreds of permissions the script would run for hours.
After some trial and error the following turned out to be the fastest method (see line 62 in the script below).
- Use the Get-View cmdlet. It’s a lot faster. See also PowerCLPowerCLI on steroids – Custom attributes.
- The Get-View cmdlet, in this format, requires the type of object (-ViewType) to be passed. We can solve this requirement by adding the EntityType attribute to the Permission node.
- We use the -Filter parameter of the Get-View cmdlet to get only the object we want. But watch out with this filter! See the next section for more details.
Get-View filter and regular expressions
As it turns out the –Filter parameter interprets the “value” as a regular expression!
That means that if you have vSphere objects whose name accidently contains one or more [regex] meta-character, the –Filter won’t return the object.
As an example, suppose you have a VirtualMachine with a name of “MyPC (v1)”, which is by the way a valid guest name. When you do the following:
001
|
$pc = Get-View -ViewType VirtualMachine -Filter @{“Name”=“MyPC (v1)”}
|
The Get-View cmdlet will not return the VirtualMachine object as you would expect.
The solution is to “escape” all the regex meta-characters in the value. Something like this
001
|
$pc = Get-View -ViewType VirtualMachine -Filter @{“Name”=“MyPC \(v1\)”}
|
To solve the occurrence of regex meta-characters in the script the lines 58..60 were added.
Note: these aren’t all the regex meta-characters! Depending on your environment and the object names you used you will have to update these lines!
“True” is not $true
In the Permission nodes there are two attributes that represent a Boolean value. But when you access these attribute values you will notice that they are text representations (strings) of the actual Boolean values.
In the Permission object we need to pass two Boolean values.
So we have to convert the node attribute values from strings to Booleans.
This can be done like this:
001
|
$perm.Group = &{if($_.Group -eq “true”) {$true} else {$false}}
|
The import script
Below the actual script that will recreate all custom roles and set all permissions as defined in the XML file.
001
002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 |
function New-Role
{ param($name, $privIds) Begin{} Process{ $roleId = $authMgr.AddAuthorizationRole($name,$privIds) } End{ return $roleId } } function Set-Permission { param( [VMware.Vim.ManagedEntity]$object, [VMware.Vim.Permission]$permission ) Begin{} Process{ $perms = $authMgr.SetEntityPermissions($object.MoRef,@($permission)) } End{ return } } # Create hash table with the current roles $authMgr = Get-View AuthorizationManager $roleHash = @{} $authMgr.RoleList | % { $roleHash[$_.Name] = $_.RoleId } # Read XML file $XMLfile = “C:\vInventory.xml” $vInventory = “<dummy/>” $vInventory.Load($XMLfile) # Define Xpaths for the roles and the permissions $XpathRoles = “Inventory/Roles/Role” $XpathPermissions = “Inventory/Permissions/Permission” # Create custom roles $vInventory.SelectNodes($XpathRoles) | % { if(-not $roleHash.ContainsKey($_.Name)){ $privArray = @() $_.Privilege | % { $privArray += $_.Name } $roleHash[$_.Name] = (New-Role $_.Name $privArray) } } # Set permissions $vInventory.SelectNodes($XpathPermissions) | % { $perm = New-Object VMware.Vim.Permission $perm.group = &{if ($_.Group -eq “true”) {$true} else {$false}} $perm.principal = $_.Principal $perm.propagate = &{if($_.Propagate -eq “true”) {$true} else {$false}} $perm.roleId = $roleHash[$_.Role] $EntityName = $_.Entity.Replace(“(“,“\(“).Replace(“)”,“\)”) $entity = Get-View -ViewType $_.EntityType -Filter @{“Name”=$EntityName} Set-Permission $entity $perm |
Since it was impractical (and even impossible) to test the script in all possible environments I would strongly advise to test the script thoroughly before using it in your production environment !
Hi, did you have a reply for your comment or any other way to do it ? I have the same case with duplicate name ?
Hi, i have to migrate a vcenter from 5.5 to 6.5 and i need to take into account that i have different objects in my vSphere environment with the same name : hundred of Ressource pools with the same name…Is there any possibility to adapt the script ? Thks !!
How to use that .. i have exported file .. Now what would be the command to run this
Do you have an updated script to work with duplicate object names or more specifically folder names? Does this script require v2.0? I’m getting a few errors:
Index operation failed; the array index evaluated to null at $roleHash[$_.Name] = $_.RoleId
Method invocation failed because [System.Object[]] doesn’t contain a method named ‘AddAuthorizationRole’.
That makes sense now why LucD’s suggestion didn’t work for me. The forum is dropping out the dummy variable in my line. Here it is with underscores…
$vInventory =“__”
Changing line 35 to “$vInventory =“”” worked for me. All custom roles are added properly except for the last one. I get the same error that Rj.Aguilera gets. I’ll just add that one manually for now.
Hey LucD – Thanks for the Export/Import script. This will prove very useful for me in my upgrade from vCenter 2.5 to 4.1. I’m testing it in my lab environment and I’m getting an error on the import. ( I got your fixed export script on the VMware forums.)
I updated line 35 as mentioned above and I’m getting the error below.
Any help you can provide is appreciated!
———————-
Cannot convert value “” to type “System.Xml.XmlDocument”. Error: “Root element is missing.”
At C:\VM_permissions_import.ps1:36 char:17
+ [XML]$vInventory <<<< = ""
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMet
adataException
+ FullyQualifiedErrorId : RuntimeException
Nice work again Alan,
I’m stealing some snippets of this to periodically re-create roles in my test environment from prod.
I did encounter the same errors as Simon… So I opted to use a different method of setting up the xml template.
function create-XMLTemplate([String]$XMLTemplateFile)
{
$input | Out-File $XMLTemplateFile -encoding UTF8
}
$vInventory = New-Object XML
$vInventoryData = @”@
$vInventoryData | create-XMLTemplate $rolesReportLocation
$vInventory.load($rolesReportLocation)
Thanks for saving me some time… again 🙂
Doug
Nice work again Alan,
I’m stealing some snippets of this to periodically re-create roles in my test environment from prod.
Thanks for saving me some time… again 🙂
Doug
Hi. Great job LucD!
I get this error
Exception calling “SetEntityPermissions” with “2” argument(s): “entity”
At C:\Users\A\AppData\Local\Temp\2\116fb4a3-242b-4d1f-814d-9b8278aeabc3.p
s1:54 char:43
+ $perms = $authMgr.SetEntityPermissions <<<< ($object.MoRef,@($permission)
)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Hi Luc, I now get this error:
Cannot convert value “[/xml]” to type “System.Xml.XmlDocument”. Error: “Data at the root level is invalid. Line 1, position 1.”
At :line:36 char:11
+ $vInventory <<<< = "[/xml]"
Simon, in PS v2 line 35 should be
$vInventory = “”
Can you give that a try ?
Hi Alan, I’m trying to run this import script and I am getting the following error:
Exception calling “AddAuthorizationRole” with “2” argument(s): “A specified parameter was not correct.
privIds”
At :line:8 char:39
+ $roleId = $authMgr.AddAuthorizationRole <<<< ($name,$privIds)
Any idea?
Simon
Hi Rutch, Change line 35 to this:
[XML]$vInventory = “”
Regards
Simon
Iam getting the following error on inport. Any ideas?
[vSphere PowerCLI] C:\Program Files\VMware\Infrastructure\vSphere PowerCLI> $vIn
ventory.Load($XMLfile)
Method invocation failed because [System.String] doesn’t contain a method named
‘Load’.
At line:1 char:17
+ $vInventory.Load <<<< ($XMLfile)
+ CategoryInfo : InvalidOperation: (Load:String) [], RuntimeExcep
tion
+ FullyQualifiedErrorId : MethodNotFound