Saturday, April 28, 2018

PowerCLI - Batch migrate VM network adapter

Back to VMware basic operational tasks: I had to migrate VMs from one network to another, which roughly translates to changing the portgoups Pretty simple and straightforward. Since the task was for several VMs, I automatically excluded clicking through the UI. That sent me to PowerCLI and now the simple task became a bit more complicated because instead on relying in real time on my hand-eye coordination for changing a portgroup, I would have to rely on an input file.

The input file is in CSV format and has four columns: VM name, source portgroup, destination portgroup and reboot (boolean value to see if reboot the VM or not). You may ask why using the source portgroup as input - I am using it to check that the VM actually has one network adapter connected to that portgroup and I am not randomly migrating everything I find on that VM.

The CSV file looks like this:
vmName,srcPg,dstPg,reboot
vm-1abc*,pg-prod-101,pg-prod-110,false
vm-2def*,pg-prod-101,pg-prod-110,false

I am also using wildcards in the name of the VMs. The reason behind this is the VMs have a very long and randomly generated name which is different from the hostname. For example, actual VM name is vm-1abc-yetcg-93763-andbv-34781, while hostname is vm-1abc. How I am checking that the wildcard does not match multiple VMs, you will see in the description below.

The migration script does the following:
  1. takes as input the CSV file and tries to load and read the CSV file; if it fails, it will exit the execution
  2. for each line in the CSV file it searches the VM in vCenter server inventory
  3. once the VM has been uniquely identified, it searches for a network adapter connected to source portgroup as defined in input file; it doesn't find it or finds multiple portgroups, it does not process the VM
  4. once the source portgroup is identified it changes the network adapter mapping to destination portgroup (as defined in input file)
  5. if reboot is required, it will issue a soft reboot to the VM
  6. and it goes to the next VM in the list

And now the code: as usual, please use it carefully as it has not been tested for all situations. Also, PowerCLI session from where the script will be run needs to be connected to vCenter Server as the script does not handle this. 



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
param(
 [Parameter(Mandatory=$true)][string]$csvVmList
)

function VmChangeNetwork($vmName,$srcPg,$dstPg,$reboot){
  Write-Host "processing:" $vmName
  Write-Host "  src PG:" $srcPg "dst PG:" $dstPg "reboot required:" $reboot

  Try {
      $v = Get-VM | Where {$_.Name -like "$vmName"}
  }
  Catch {
    Write-Host $_.Exception.Message $_.Exception.ItemName
  }

  if ($v.Count -eq 1){
    $srcPgExist = $v  | Get-NetworkAdapter | Where {$_.NetworkName -eq $srcPg}
    if ($srcPgExist.Count -eq 1) {
      $v  | Get-NetworkAdapter | Where {$_.NetworkName -eq $srcPg} | Set-NetworkAdapter -NetworkName $dstPg -Confirm:$false
      if (($reboot.ToLower() -match "true") -and ($v.PowerState -match "PoweredOn")){
        Write-Host " rebooting VM"
        Restart-VM -VM $v -RunAsync -Confirm $False
      }
    } elseif ($srcPgExist.Count -eq 0) {
      Write-Host " no adapters connected to" $srcPg "found"
    } else {
      Write-Host " multiple adapters connected to" $srcPg "found"
    }


  } elseif ($v.Count -eq 0) {
    Write-Host " "$vmName "was not found"
  } else {
    Write-Host " "$v.Count "VMs found with name" $vmName
  }
  Write-Host ""
}

# load CSV file
Try {
  $vmList = Import-Csv $csvVmList
}
Catch {
  Write-Host -foregroundcolor red " File is not accessible"
 exit
}

# process VMs
foreach ($vm in $vmList){
  VmChangeNetwork -vmName $vm.vmName -srcPg $vm.srcPg -dstPg $vm.dstPg -reboot $vm.reboot
}

No comments: