VMware PowerCLI – Script de Migration du vCenter

Je vous présente aujourd’hui un script que j’ai développé avec l’aide de ceux proposés par LucD, il permet de faire la migration depuis un ancien vCenter vers un nouveau « from scratch », dans mon cas depuis un vCSA 5.5 vers une architecture avec deux vCSA 6.0 avec PSC externe en Linked Mode.

Etant donné que je n’ai pas trouvé de solution (Pour l’instant :D) pour migrer les Utilisateurs & Groupes SSO, ils devront donc être ajoutés à la main…

vsphere-permissions

Prérequis :

  • Ajouter le vCenter au domaine
  • Ajouter les Utilisateur & Groupes SSO (Manuel pour l’instant)
  • Attacher les ESXi au vCenter

Pour le reste le script s’occupe de tout, il va recréer les différents Roles avec les bon Privilèges, créer les différents Folders et y insérer les VM puis ajouter les Permissions. Je conseille d’ouvrir un nouveau PowerCLI pour partir propre sans liaison à d’autres vCenter.

function ConnectServer([string] $strVCenterName) {
    Connect-VIServer -Server $strVCenterName -User $strVcenterUser -Password $strVcenterPass -SaveCredentials
}
 
function ExportFolder([string] $dcName){
New-VIProperty -Name 'BlueFolderPath' -ObjectType 'VirtualMachine' -Value {
    param($vm)

    function Get-ParentName{
        param($object)

        if($object.Folder){
            $blue = Get-ParentName $object.Folder
            $name = $object.Folder.Name
        }
        elseif($object.Parent -and $object.Parent.GetType().Name -like "Folder*"){
            $blue = Get-ParentName $object.Parent
            $name = $object.Parent.Name
        }
        elseif($object.ParentFolder){
            $blue = Get-ParentName $object.ParentFolder
            $name = $object.ParentFolder.Name
        }
        if("vm","Datacenters" -notcontains $name){
            $blue + "/" + $name
        }
        else{
            $blue
        }
    }

    (Get-ParentName $vm).Remove(0,1)
} -Force | Out-Null 

Get-VM -Location (Get-Datacenter -Name $dcName) | 
Select Name,BlueFolderPath |
Export-Csv $CSVPath -NoTypeInformation -UseCulture 
}

function ImportFolder([string] $newDatacenter){
$startFolder = Get-Folder -Name vm -Location (Get-Datacenter -Name $newDatacenter)

Import-Csv $CSVPath -UseCulture | %{
    $location = $startFolder
    $_.BlueFolderPath.TrimStart('/').Split('/') | %{
        $tgtFolder = Get-Folder -Name $_ -Location $location -ErrorAction SilentlyContinue
        if(!$tgtFolder){
            $location = New-Folder -Name $_ -Location $location
        }
        else{
            $location = $tgtFolder
        }
    }
    
    $vm = Get-VM -Name $_.Name -ErrorAction SilentlyContinue
    if($vm){
        Move-VM -VM $vm -Destination $location -Confirm:$false 
    }
}
}

function ExportSSO([string] $XMLfile){
# Root of the XML file
$global:vInventory = [xml]"<Inventory></Inventory>"

# Functions
function New-XmlNode{
	param($node, $nodeName)

	$tmp = $global:vInventory.CreateElement($nodeName)
	$node.AppendChild($tmp)
}

function Set-XmlAttribute{
	param($node, $name, $value)

	$node.SetAttribute($name, $value)
}
function Get-XmlNode{
	param ($path)
	$global:vInventory.SelectNodes($path)
}

function Get-Roles{
  begin{
    $authMgr = Get-View AuthorizationManager
    $report = @()
  }
  process{
    foreach($role in $authMgr.roleList){
      $ret = New-Object PSObject
      $ret | Add-Member -Type noteproperty -Name "Name" -Value $role.name
      $ret | Add-Member -Type noteproperty -Name "Label" -Value $role.info.label
      $ret | Add-Member -Type noteproperty -Name "Summary" -Value $role.info.summary
      $ret | Add-Member -Type noteproperty -Name "RoleId" -Value $role.roleId
      $ret | Add-Member -Type noteproperty -Name "System" -Value $role.system
      $ret | Add-Member -Type noteproperty -Name "Privilege" -Value $role.privilege
      $report += $ret
    }
  }
  end{
    return $report
  }
}
function Get-Permissions
{
  begin{
    $report = @()
    $authMgr = Get-View AuthorizationManager
    $roleHash = @{}
    $authMgr.RoleList | %{
      $roleHash[$_.RoleId] = $_.Name
    }
  }
  process{
    $perms = $authMgr.RetrieveAllPermissions()
    foreach($perm in $perms){
      $ret = New-Object PSObject
      $entity = Get-View $perm.Entity
      $ret | Add-Member -Type noteproperty -Name "Entity" -Value $entity.Name
      $ret | Add-Member -Type noteproperty -Name "EntityType" -Value $entity.gettype().Name
      $ret | Add-Member -Type noteproperty -Name "Group" -Value $perm.Group
      $ret | Add-Member -Type noteproperty -Name "Principal" -Value $perm.Principal
      $ret | Add-Member -Type noteproperty -Name "Propagate" -Value $perm.Propagate
      $ret | Add-Member -Type noteproperty -Name "Role" -Value $roleHash[$perm.RoleId]
      $report += $ret
    }
  }
  end{
    return $report
  }
}
$global:vInventory = [xml]"<Inventory><Roles/><Permissions/></Inventory>"

# Main
# Roles
  $XMLRoles = Get-XmlNode "Inventory/Roles"
Get-Roles | where {-not $_.System} | % {
  $XMLRole = New-XmlNode $XMLRoles "Role"
  Set-XmlAttribute $XMLRole "Name" $_.Name
  Set-XmlAttribute $XMLRole "Label" $_.Label
  Set-XmlAttribute $XMLRole "Summary" $_.Summary
  $_.Privilege | % {
    $XMLPrivilege = New-XmlNode $XMLRole "Privilege"
    Set-XmlAttribute $XMLPrivilege "Name" $_
  }
}

# Permissions
$XMLPermissions = Get-XmlNode "Inventory/Permissions"
Get-Permissions | % {
  $XMLPerm = New-XmlNode $XMLPermissions "Permission"
  Set-XmlAttribute $XMLPerm "Entity" $_.Entity
  Set-XmlAttribute $XMLPerm "EntityType" $_.EntityType
  Set-XmlAttribute $XMLPerm "Group" $_.Group
  Set-XmlAttribute $XMLPerm "Principal" $_.Principal
  Set-XmlAttribute $XMLPerm "Propagate" $_.Propagate
  Set-XmlAttribute $XMLPerm "Role" $_.Role
}

# Create XML file
$global:vInventory.Save($XMLfile)
}

function ImportSSO([string] $XMLfile){
# Functions
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
}
}

# Main
# Create hash table with the current roles
$authMgr = Get-View AuthorizationManager
$roleHash = @{}
$authMgr.RoleList | % {
    $roleHash[$_.Name] = $_.RoleId
}

# Read XML file
$vInventory = [xml]"<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(")","\)")
    $EntityName = $EntityName.Replace("[","\[").Replace("]","\]")
    $EntityName = $EntityName.Replace("{","\{").Replace("}","\}")

    $entity = Get-View -ViewType $_.EntityType -Filter @{"Name"=("^" + $EntityName + "$")}
    Set-Permission $entity $perm
}
}

# Variables
$XMLPath = "C:\vCenter_SSO.xml"
$CSVPath = "C:\vCenter_VM_Folders.csv"

# Delete Files
If (Test-Path $XMLPath){
	Remove-Item $XMLPath
}
If (Test-Path $CSVPath){
	Remove-Item $CSVPath
}

# vCenter Login
write-host ""
write-host -nonewline "vCenter User (ex. [email protected]) : "
$strVcenterUser = read-host 

write-host -nonewline "vCenter Password : "
$strVcenterPass = read-host 

# Legacy vCenter Values 
write-host ""
write-host -nonewline "Legacy vCenter FQDN : "
$vCenterLegacy = read-host
write-host -nonewline "Legacy Datacenter Name : "
$DCLegacy = read-host

# New vCenter Values 
write-host ""
write-host -nonewline "New vCenter FQDN : "
$vCenterNew = read-host
write-host -nonewline "New Datacenter Name : "
$DCNew = read-host

# Legacy vCenter Scripts
Write-Host "";Write-Host "Connecting to" $vCenterLegacy -ForegroundColor Yellow
ConnectServer $vCenterLegacy
Write-Host "";Write-Host "Exporting Folders from" $DCLegacy -ForegroundColor Yellow
ExportFolder $DCLegacy
Write-Host "Exporting Done !" -ForegroundColor Green
Write-Host "";Write-Host "Exporting SSO to" $XMLPath -ForegroundColor Yellow
ExportSSO $XMLPath
Write-Host "Exporting Done !" -ForegroundColor Green

# Disconnect Legacy vCenter
Disconnect-VIServer -Server $vCenterLegacy -Confirm:$false

# Pause
Write-Host"";Write-Host "Press Enter to Import !" -ForegroundColor Red
pause

# New vCenter Scripts
Write-Host "Connecting to" $vCenterNew -ForegroundColor Yellow
ConnectServer $vCenterNew
Write-Host"";Write-Host "Importing Folders to" $DCNew -ForegroundColor Yellow
ImportFolder $DCNew
Write-Host "Importing Done !" -ForegroundColor Green
Write-Host"";Write-Host "Importing SSO from" $XMLPath -ForegroundColor Yellow
ImportSSO $XMLPath
Write-Host"";Write-Host "Importing Done !" -ForegroundColor Green

# Disconnect New vCenter
Disconnect-VIServer -Server $vCenterNew -Confirm:$false

# Done
Write-Host"";Write-Host "Script succesfully executed !" -ForegroundColor Green
Migration vCenter v0.1


...BofBienTrès BienTop ! (Soit le premier à voter)
Loading...

Mathieu

Je suis actuellement Ingénieur Système spécialisé dans le design d'environnements cloud virtualisés. Adepte des technologies de VMware, Nutanix, Citrix ou Microsoft je propose à travers ce blog diverses astuces de troubleshooting.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *