VMware Cloud Community
chriswizemen
Contributor
Contributor

Move-VM VMs with Multiple Network Interfaces

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? 

0 Kudos
11 Replies
LucD
Leadership
Leadership

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

0 Kudos
chriswizemen
Contributor
Contributor

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.

0 Kudos
chriswizemen
Contributor
Contributor

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.

0 Kudos
LucD
Leadership
Leadership

What do you mean by "read-only variable"?
Can you show your relevant code?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
chriswizemen
Contributor
Contributor

$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
0 Kudos
LucD
Leadership
Leadership

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

0 Kudos
chriswizemen
Contributor
Contributor

NetworkName is readonly.

When I try to change $DestAdapter.NetworkName it errors out.

Tags (1)
0 Kudos
LucD
Leadership
Leadership

0 Kudos
chriswizemen
Contributor
Contributor

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
0 Kudos
LucD
Leadership
Leadership

To declare an array you need @, not $

$DestNetworkArray = @()


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
chriswizemen
Contributor
Contributor

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.

Tags (1)