Automatizzazione step di Disaster Recovery “asincrono” relativo ai Distribuited Virtual Switch

Posted on 25 luglio 2011 di

0


In una situazione di DR asincrono, nel quale si decide di utilizzare 2 virtual center (uno di produzione ed uno di DR, mirrorando solo lo storage), il problema principale è l’utilizzo dei dvswitch sui due virtual center. Infatti proprio per l’architettura di vsphere, quando si andranno a registrare sul sito di DR (anche a scopo di test ad esempio) prima i datastore mirrorati da produzione e poi le macchine spente che ci sono sopra, esse mostreranno grossi problemi sulle schede di rete virtuali con errore “invalid backin” che stà a significare che non ritrovano nel nuovo vcenter i riferimenti ai dvportgroup. E ci mancherebbe altro: i dvportgroup nonostante di chiamino allo stesso modo e presentino le stesse vlan…hanno uuid del tutto diversi!

Grazie alle funzioni create da LucD sui distribuited dvswitch questo problema è superabile sebbene sia richiesto un lavoro di fino a causa del fatto che le macchine virtuali con più schede di rete su PROD devono avere esattamente le stesse network assegnate anche su DR.

Lo script è migliorabile soprattutto dal lato esportazioni in csv che di seguito riporto: le ho lasciate perchè nel mio caso esse sono schedulate periodicamente in altri script…ma se volete potete assegnare all’ array che state lavorando direttamente il comando realtivo di GET…senza esportare e poi reimportare.

Di seguito lo scriptone…

function Get-dvSwNetworkAdapter{
param([parameter(Mandatory = $true, ValueFromPipeline = $true)][VMware.VimAutomation.Client20.VirtualMachineImpl[]]$VM
)

process{
$VM | Get-View | %{
$vmObj = $_
$vmObj.Config.Hardware.Device | where {“VirtualEthernetCard”,”VirtualVmxnet” -contains $_.GetType().BaseType.Name} | %{
$net = $_
New-Object PSObject -Property @{
MacAddress = $net.MacAddress
WakeOnLanEnabled = $net.WakeOnLanEnabled
NetworkName = &{
if($net.Backing.GetType().Name -eq “VirtualEthernetCardNetworkBackingInfo”){
(Get-View $_.Backing.network).Name
}
else{
($vmObj.Network | %{Get-View $_} | where{$_.Key -eq $net.Backing.Port.PortgroupKey}).Name
}
}
Type = $net.GetType().Name
ParentId = $vmObj.MoRef.Type + “-” + $vmObj.MoRef.Value
ConnectionState = New-Object PSObject -Property @{
Connected = $net.Connectable.Connected
StartConnected = $net.Connectable.StartConnected
}
Id = $vmObj.MoRef.Type + “-” + $vmObj.MoRef.Value + “/” + $net.Key
Name = $net.DeviceInfo.Label
}
}
}
}
}

function Set-dvSwNetworkAdapter{
param([parameter(Mandatory = $true, ValueFromPipeline = $true)][PSCustomObject[]]$NetworkAdapter,
[parameter(Mandatory = $true)][string]$NetworkName,
[switch]$StartConnected,
[switch]$Connected
)

process{
$NetworkAdapter | %{
$netAdapter = $_
$vm = Get-View $netAdapter.ParentId
$esx = Get-View $vm.Runtime.Host
$newNet = $esx.Network | %{Get-View $_} | where {$_.Name -eq $NetworkName}
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec

$dev = New-Object VMware.Vim.VirtualDeviceConfigSpec
$dev.operation = “edit”
$dev.device = $vm.Config.Hardware.Device | where {$_.GetType().Name -eq $netAdapter.Type -and $_.MacAddress -eq $netAdapter.MacAddress}

# Determine backing type
switch($newNet.GetType().Name){
“Network” {
$dev.device.backing = New-Object VMware.Vim.VirtualEthernetCardNetworkBackingInfo
$dev.device.backing.deviceName = $NetworkName
}
“DistributedVirtualPortgroup” {
$dev.device.Backing = New-Object VMware.Vim.VirtualEthernetCardDistributedVirtualPortBackingInfo
$dev.device.backing.port = New-Object VMware.Vim.DistributedVirtualSwitchPortConnection

$dev.device.backing.port.switchUuid = (Get-View $newNet.Config.DistributedVirtualSwitch).Uuid
$dev.device.backing.port.portgroupKey = $newNet.Config.Key
}
}
if($Connected -ne $null){
$dev.Device.Connectable.Connected = $Connected
}
if($StartConnected -ne $null){
$dev.Device.Connectable.StartConnected = $StartConnected
}
$spec.deviceChange += $dev
$taskMoRef = $vm.ReconfigVM_Task($spec)

$task = Get-View $taskMoRef
while(“running”,”queued” -contains $task.Info.State){
$task.UpdateViewData(“Info”)
}
$returnNetworkAdapter = $netAdapter
$returnNetworkAdapter.NetworkName = $NetworkName
$returnNetworkAdapter.ConnectionState.StartConnected = $dev.Device.Connectable.StartConnected
$returnNetworkAdapter.ConnectionState.Connected = $dev.Device.Connectable.Connected
$returnNetworkAdapter
}
}
}

Connect-VIServer vcenter_produzione

#Dettaglia solo macchine in cluster (perchè usano dvswitch)

$machines = Get-Cluster | where {$_.Name -eq “CLUSTER (primary site)” } | Get-VM
Get-Cluster | where {$_.Name -eq “CLUSTER (primary site)” } | Get-VM | Export-Csv “C:\Dettaglio_VM_sito_PROD.csv” -Confirm:$false

#esporta le info di rete dei dvswitch nel csv

Get-dvSwNetworkAdapter -VM (Get-VM $machines) | Export-Csv “C:\Dettaglio_rete_dvswitch_VM_sito_PROD.csv” -Confirm:$false

Disconnect-VIServer vcenter_produzione

Connect-VIServer vcenter_sede_dr

#macchine in cluster (dvswitch) attualmente su dr

$drmachines = Get-Cluster | where {$_.Name -eq “Cluster MUSOLINO (dr site)” } | Get-VM

#macchine in cluster (dvswitch) salvate da produzione

$prodmachines = Import-Csv “C:\Dettaglio_VM_sito_PROD.csv”

#portgroup delle macchine in cluster (dvswitch) salvate da produzione

$dvSwNetworkAdapters = Import-csv “C:\Dettaglio_rete_dvswitch_VM_sito_PROD.csv”

# a questo punto tramite annidamenti di cicli for ed if vengono settate per ogni network adapter la network name sul dvportgroup in base ai
# confronti di matching tra i record salvati sui csv (PROD) e l’attuale stato delle macchine in cluster (DR), il tutto ovviamente se le macchine si
# chiamano allo stesso modo e se sono presenti nel cluster del sito di dr

# -ieq $prodmachine.Name)
foreach ($drmachine in $drmachines) {
foreach ($prodmachine in $prodmachines) {
if ($prodmachine.Name -eq $drmachine.Name){
foreach ($dvSwNetworkAdapter in $dvSwNetworkAdapters) {
if ($dvSwNetworkAdapter.ParentId -eq $prodmachine.Id) {
write-host “Stò settando la rete $($dvSwNetworkAdapter.NetworkName) su $($dvSwNetworkAdapter.Name) della VM $($drmachine.Name)”
Get-dvSwNetworkAdapter -VM $drmachine | where {$_.Name -eq “$($dvSwNetworkAdapter.Name)”} | Set-dvSwNetworkAdapter -NetworkName “$($dvSwNetworkAdapter.NetworkName)” -StartConnected:$false
}
}
}
}
}

Disconnect-VIServer vcenter_DR