I am trying to script cross-cluster vmotion using Move-VM. I am struggling with VMs which have multiple network adapters. Single network adapter migrations where the portgroup exists on both ends work great.
What I can not figure out how to handle are machines with multiple NICs. This seems to boil back to my usage of the PortGroup option of Move-VM.
There are two problems I've found.
1) Get-virtualportgroup only shows unique entries, so VMs with multiple NICs to a single portgroup fail.
2) All my VMs with multiple NICs appear to be failing. I interpret that passing an array of portgroups to -PortGroup doesnt actually work.
Actual Problem: How can I move a VM with four network interfaces, and change two of them during migration.
Example:
VM1:
NIC1 connected to datacenterwidePG1
NIC2 connected to datacenterwidePG1
NIC3 connected to clusterspecificPG1
NIC4 connected to clusterspecificPG2
In this example, I need to update NIC3 and NIC4 to point to newclusterPG1 and newclusterPG2, during the migration.
My current attempt is to use PGSourceArray = Get-VM | Get-VirtualPortGroup, and then use foreach to check each portgroup exists on the destination. If it doesnt, find its replacement, and add that to PGDestArray, which I then pass along to Move-VM -Portgroup <PGDestArray>.
The challenge I was attempting to solve is that our storage fabric has different names between clusters. I wrote logic to come up with the correct name, and retrieve the correct object from get-virtualportgroup, which is then inserted into the array in lieu of the source portgroup.
Can I accomplish this with the -NetworkAdapter option?
I'm wondering if I can do get-networkadapter $vm, foreach each interface, and change the "NetworkName" attribute, and feed that object back into an array, which I then use to feed move-vm -NetworkAdapter? Do I need to change more values?
Did you make sure that the arrays you pass on the Network and NetworkAdapter parameters are sync-ed?
The Get-NetworkAdapter cmdlet returns all vNICs for a VM, and the resulting object(s) contain the NetworkName, which is the portgroup.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
LucD, thanks for responding.
In my attempt yesterday, I was ONLY using the -Portgroup option.
Today, I will attempt to modify my process to iterate through network adapter, and change the "network" within each adapter to be the appropriate portgroup.
I appreciate the confirmation and detail.
Ok.
I'm stuck with a read-only variable when I try to change the NetworkName of the NetworkAdapter object I get from Get-NetworkAdapter $vm.
Maybe I can step back.
How do I run Move-VM on a VM with two network interfaces.
One exists on source/destination clusters.
One needs to be re-mapped on the destination cluster.
The documentation for Move-VM is real limited on how to use -Network or -NetworkAdapter. If there is better documentation than "get-help move-vm -full", please point me in a direction.
What do you mean by "read-only variable"?
Can you show your relevant code?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
$VMNetworkInterfaces = @()
$NetworkToCheck = $null
$getnetwork = $null
$oldInterfaceName = $null
$newInterfaceName = $null
$networkname = $null
$DestNetworkArray = $()
$VMNetworkInterfaces = (Get-NetworkAdapter $vm -ErrorAction SilentlyContinue)
Write-Host "Debug: Network Interfaces before: " $VMNetworkInterfaces
if ($VMNetworkInterfaces)
{
foreach ($NetworkToCheck in $VMNetworkInterfaces)
{
Write-Host "Debug: network = " $NetworkToCheck
$networkname = $NetworkToCheck.NetworkName
$getnetwork = (get-virtualportgroup -Name $networkname -ErrorAction SilentlyContinue)
Write-host "Debug: getnetwork" $getnetwork
if ($networkname -like '*iscsi*')
{
#Attempt to rename by cluster naming convention: crop the first 10 characters "iscsi-###-"
$oldInterfaceName = $networkname
$newInterfaceName = $oldInterfaceName.Substring(0,10) + $DestCluster
# Retrieve the object for the regex'd new iscsi network interface.
$newInterface = Get-VirtualPortGroup -Name $newInterfaceName -ErrorAction SilentlyContinue
# Add the interface to the new array
Write-Host "Debug: oldinterface: " $oldInterfaceName
Write-Host "Debug: newinterface: " $newInterfaceName
# $NetworkToCheck.NetworkName = $newInterface
# Yields Powershell error: 'NetworkName' is a ReadOnly property.
$DestAdapter = $NetworkToCheck
$DestAdapter.NetworkName = $newInterface
Write-Host "Debug: DestAdapter: " $DestAdapter
$NetworkToCheck = $DestAdapter
} #end of iscsi loop
Write-Host "Debug: existed and added: " $NetworkToCheck
Write-Host "Debug: existed and added: " $NetworkToCheck.NetworkName
$DestNetworkArray += $NetworkToCheck
} #end of foreach loop
} #end of networkinterface loop
You are trying to change a property in an object returned by Get-NetworkAdapter.
You can't do that, these are read-only objects.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
NetworkName is readonly.
When I try to change $DestAdapter.NetworkName it errors out.
Have a look at move-vm script placing port groups on wrong adapte... - VMware Technology Network VMTN
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
In my original script, I run into an error.
Method invocation failed because [VMware.VimAutomation.ViCore.Impl.V1.VirtualDevice.NetworkAdapterImpl] does not
contain a method named 'op_Addition'.
+ $DestNetworkArray += $NetworkToCheck
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
I can actually replicate it with your sample code. Yours works, my expansion fails.
$vm = Get-VM $vmname
$networkadapters = @()
$destinationPortgroup = Get-NetworkAdapter -VM $vm | Sort-Object -Property Name | ForEach-Object -Process {
$networkadapters += $_
Write-Host "array" $networkadapters
Write-Host "index" $networkadapters[-1]
Get-VirtualPortGroup -Name $networkadapters[-1].NetworkName
Write-Host ( Get-VirtualPortGroup -Name $networkadapters[-1].NetworkName)
}
Write-Host "LucD's network array " $networkadapters
Write-Host "LucD's pg array " $destinationPortgroup
Write-Host " "
$destinationPortGroup = @()
$networkadapters = @()
$networkadapters = (Get-NetworkAdapter -VM $vm | Sort-Object -Property Name)
Foreach ($network in $networkadapters)
{
Write-Host "array" $networkadapters
Write-Host "index" $network
$destinationPortgroup += Get-VirtualPortGroup -Name $network.NetworkName
Write-Host ( Get-VirtualPortGroup -Name $network.NetworkName)
$newnetworkarray += $network
}
Write-Host "Expanded " $networkadapters
Write-Host "Expanded " $destinationPortgroup
Write-Host "Expanded " $newnetworkarray
Can you explain why I can't augment my array with this object but in a Process it can?
Method invocation failed because [VMware.VimAutomation.ViCore.Impl.V1.VirtualDevice.NetworkAdapterImpl] does not
contain a method named 'op_Addition'.
At testing-bulkmove.ps1:33 char:5
+ $newnetworkarray += $network
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
To declare an array you need @, not $
$DestNetworkArray = @()
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks for your time today LucD.
I was approaching the problem the wrong way.
I thought you could use either "Move-VM -PortGroup" or "Move-VM -NetworkAdapter". Now that I'm using them combined, things are working.