VMware Cloud Community
zenivox
Hot Shot
Hot Shot
Jump to solution

Copying PVLANs and related PGs from dVS to dVS

Hello, I wrote a simple script to copy all PGs (including PVLANs) from an existing dVS to a new one. However I can't find a way if there is a way at all, to complete the PVLANs portgroup assignment part. I looked at Luc's function Set-dVSwPgPVLAN but I don't find the way to use it in a loop, cause if I pass info using a zip file I only get the BaseName property but not the secondary vlan, while if I use the Get-VDSwitchPrivateVlan to collect info I don't get the BaseName and get the secondary vlan. Here's the script:

#copy PGs from source dVS

Get-VDSwitch -Name TST-DVS1 | Get-VDPortgroup | where{$_.VlanConfiguration -notmatch "PVLAN" -and $_.Name -notmatch "DVUplinks"} |

Foreach {

Export-VDPortGroup -VDPortGroup $_ -Description “Backup of $($_.Name) PG” -Destination “C:\Users\Documents\DVS\$($_.Name).Zip”

}

#copy PGs to destination dVS

Get-ChildItem “C:\Users\Documents\DVS” | Foreach {

New-VDPortgroup -VDSwitch  TST-DVS2 -Name “$($_.BaseName)_” -BackupPath $_.FullName

}

#copy PVLANs configs from source to destination dVS

Get-VDSwitch -Name  TST-DVS1 | Get-VDSwitchPrivateVlan | Foreach {

Get-VDSwitch -Name  TST-DVS2 | New-VDSwitchPrivateVlan -PrimaryVlanId $_.PrimaryVlanId -SecondaryVlanId $_.SecondaryVlanId -PrivateVlanType $_.PrivateVlanType

}

#copy PGs from source dVS

Get-VDSwitch -Name  TST-DVS1 | Get-VDPortgroup | where{$_.VlanConfiguration -match "PVLAN"} |

Foreach {

Export-VDPortGroup -VDPortGroup $_ -Description “Backup of $($_.Name) PG” -Destination “C:\Users\Documents\DVS\PVLAN\$($_.Name).Zip”

}

## Now import PVLAN zip files into dVS using Web Client

regarding the last part commented out which is manual, it only works if no other dvSwitches with same ports are present. In fact in my case it does not work as probably it detects the same name already in an other dVS. So the part I'm missing is the last one, the PVLAN portgroup assignment.

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

When I use my Set-dvSwPgVLAN function, I can assign the PVLANs to the portgroups.

I use a CSV to store the required info.

$srcVDS = 'vdsDEV01'

$tgtVDS = 'vdsDEV02'

$tempFolder = 'C:\Temp\VDS'

function Set-dVSwPgPVLAN{

    param($dvSw, $dvPgName, $pvlanNr)

   

    # Find the portgroup

    $dvSw.Portgroup | % {

       $dvPgTemp = Get-View -Id $_

       if($dvPgTemp.Name -eq $dvPgName){

         $dvPg = $dvPgTemp

       }

    }

   

    $spec = New-Object VMware.Vim.DVPortgroupConfigSpec

    $spec.defaultPortConfig = New-Object VMware.Vim.VMwareDVSPortSetting

    $spec.defaultPortConfig.vlan = New-Object VMware.Vim.VmwareDistributedVirtualSwitchPvlanSpec

    $spec.defaultPortConfig.vlan.pvlanId = $pvlanNr

   

    $dvPg.UpdateViewData()

    $spec.ConfigVersion = $dvPg.Config.ConfigVersion

   

    $taskMoRef = $dvPg.ReconfigureDVPortgroup_Task($spec)

   

    $task = Get-View $taskMoRef

    while("running","queued" -contains $task.Info.State){

        $task.UpdateViewData("Info")

    }

}

#copy PGs from source dVS 

Get-VDSwitch -Name $srcVDS | Get-VDPortgroup | where{$_.VlanConfiguration -notmatch "PVLAN" -and $_.Name -notmatch "DVUplinks"} | 

Foreach

    Export-VDPortGroup -VDPortGroup $_ -Description “Backup of $($_.Name) PG” -Destination $tempFolder\$($_.Name).Zip”

 

#copy PGs to destination dVS 

Get-ChildItem $tempFolder -Filter *.zip | Foreach

    New-VDPortgroup -VDSwitch $tgtVDS -Name $($_.BaseName)_” -BackupPath $_.FullName 

 

#copy PVLANs configs from source to destination dVS 

Get-VDSwitch -Name $srcVDS | Get-VDSwitchPrivateVlan | Foreach

    Get-VDSwitch -Name $tgtVDS |

    New-VDSwitchPrivateVlan -PrimaryVlanId $_.PrimaryVlanId -SecondaryVlanId $_.SecondaryVlanId -PrivateVlanType $_.PrivateVlanType 

 

#copy PGs from source dVS 

Get-VDSwitch -Name $srcVDS | Get-VDPortgroup | where{$_.VlanConfiguration -match "PVLAN"} | 

Select Name,@{N='VLANId';E={$_.VlanConfiguration.SecondaryVlanId}} |

Export-Csv -Path "$tempFolder\pvlan.csv" -NoTypeInformation -UseCulture

 

# Now import PVLAN zip files into dVS using Web Client

Import-Csv -Path "$tempFolder\pvlan.csv" -UseCulture | %{

    New-VDPortgroup -VDSwitch $tgtVDS -Name "$($_.Name)_"

    Set-dVSwPgPVLAN -dvSw (Get-VDSwitch -Name $tgtVDS).ExtensionData -dvPgName "$($_.Name)_" -pvlanNr $_.VLANId

}


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

View solution in original post

17 Replies
LucD
Leadership
Leadership
Jump to solution

Did you already check out Re: Listing vswitch info ?

In there I list all VLAN info, including PVLans.

Based on that information you could configure the VDS on the other side.


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

0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

Thanks, I'll check it. I'm not good at strong typing, I'll do some reading and see if I come out with something

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Let me know if it gets you somewhere, otherwise I can lend a hand.


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

zenivox
Hot Shot
Hot Shot
Jump to solution

something strange.. when I do:

Get-dvSwitch -dcName MYdc2 -dvSwName destination-DVS

I get the right output. While if I do

Get-dvSwitch -dcName MYdc1 -dvSwName source-DVS which I believe is what I need when I need to create PVLAN portgroup, I get nothing. Piping to gm it says that no object is specified. However vcenters are connected and if I use get-datacenter all is ok. I need this before using Set-dVSwPgPVLAN

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, some things to check.

Did you configure the DefaultVIServerMode to Multiple on the Set-PowerCLIConfiguration cmdlet?

Do a Get-PowerCLIConfiguration to check.

When you are sure you are working in Multiple mode, display the contents of $global:defaultviservers.

If that shows both vCenters, do a Get-VDSwitch, yes the PowerCLI cmdlet, to check if you see all VDS from both vCenters.


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

0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

Thanks Luc, user and session in Multiple mode, fine there, but I found something, no DVS in that DC returns result. In other DCs yes. DVS Versions 6 in all. vCenter in common.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Also when you use the Server parameter, explicitly referencing to the vCenter?


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

0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

sorry I rectified my post after you: The vCenter server is in common

the Get-dvSwitch does not have a server paramenter, or maybe I didn't get what you are referring to

0 Kudos
LucD
Leadership
Leadership
Jump to solution

No, I mean to use the actual cmdlet Get-VDSwitch, not my function.


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

0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

sorry my fault I haven't been clear, when I posted:

Thanks Luc, user and session in Multiple mode, fine there, but I found something, no DVS in that DC returns result. In other DCs yes. DVS Versions 6 in all. vCenter in common.

I should have wrote instead:

Thanks Luc, user and session in Multiple mode, fine there, but I found something, no DVS in that DC returns result by using your function Get-dvSwitch. In other DCs yes. DVS Versions 6 in all. vCenter in common. By using Get-VDSwitch all ok anywhere.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, forget my Get-dvSwitch function, that doesn't work correctly when connected to multiple vCenters, and has a few other issues as well.

Use the Get-VDSwitch, but make sure to pass the ExtensionData to the New-dvSwPVLAN function, something like this.

$vds = Get-VDSwitch -Name <whatever>

New-dvSwPVLAN -dvSw $vds.ExtensionData -primaryNr 2 -secondaryNr 102,202 -secondaryType "community","isolated"


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

0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

I already got that part in my initial script at the section:

  1. #copy PVLANs configs from source to destination dVS 
  2. Get-VDSwitch -Name  TST-DVS1 | Get-VDSwitchPrivateVlan | Foreach { 
  3. Get-VDSwitch -Name  TST-DVS2 | New-VDSwitchPrivateVlan -PrimaryVlanId $_.PrimaryVlanId -SecondaryVlanId $_.SecondaryVlanId -PrivateVlanType $_.PrivateVlanType}

In fact PVLANs are set in the destination DVS already. The part I'm missing is the portgroup assignment. That is where I'm struggling. If I can't use your Get-dvSwitch function I was thinking to go this way:

Get-VDSwitch ICC-Gonos-GVA | Get-VDPortgroup | where{$_.VlanConfiguration -match "PVLAN"} |

Select Name,@{N='VlanId';E={if($_.ExtensionData.Config.DefaultPortConfig.Vlan -is [VMware.Vim.VmwareDistributedVirtualSwitchPvlanSpec]){

                $_.ExtensionData.Config.DefaultPortConfig.Vlan.PvlanId

            }}} | ForEach {

               

                Set-dVSwPgPVLAN -dvSw TEST-DVS -dvPgName $_.Name -pvlanNr $_.ExtensionData.Config.DefaultPortConfig.Vlan.PvlanId 

                }

But it throws

Get-View : Cannot validate argument on parameter 'Id'. The argument is null or empty. Provide an argument that is not null or empty, and then try the

command again.

At C:\Users\Documents\functions\Set-dVSwPgPVLAN.ps1:6 char:28

+         $dvPgTemp = Get-View -Id $_

+                                  ~~

    + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView

You cannot call a method on a null-valued expression.

At C:\Users\Documents\functions\Set-dVSwPgPVLAN.ps1:17 char:2

+     $dvPg.UpdateViewData()

+     ~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException

    + FullyQualifiedErrorId : InvokeMethodOnNull

You cannot call a method on a null-valued expression.

At C:\Users\Documents\functions\Set-dVSwPgPVLAN.ps1:20 char:2

+     $taskMoRef = $dvPg.ReconfigureDVPortgroup_Task($spec)

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException

    + FullyQualifiedErrorId : InvokeMethodOnNull

Get-View : Cannot validate argument on parameter 'VIObject'. The argument is null or empty. Provide an argument that is not null or empty, and then

try the command again.

At C:\Users\Documents\functions\Set-dVSwPgPVLAN.ps1:22 char:19

+     $task = Get-View $taskMoRef

+                      ~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView

probably because the Select-Object alters the parameters.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, I see.

For my understanding, now you are doing an Export-Import to copy the VDS over.
That includes the VDPortgroups.
But the PVLAN are missing, correct?
When the VDPortgroup that has a PVLAN is created on the target, does it not have any VLANId specified?
And if they do, are those the VLANId associated with the PVLAN?


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

0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

I realize that maybe I was not clear since the beginning and I apologise for that. So here my initial script with explanations of my reasoning and reply to your questions:

#copy PGs from source dVS

Get-VDSwitch -Name TST-DVS1 | Get-VDPortgroup | where{$_.VlanConfiguration -notmatch "PVLAN" -and $_.Name -notmatch "DVUplinks"} |

Foreach {

Export-VDPortGroup -VDPortGroup $_ -Description “Backup of $($_.Name) PG” -Destination “C:\Users\Documents\DVS\$($_.Name).Zip”

}

The reason why I'm excluding the private vlans above (and this to reply your question if pvlans are missing) is because if I export all vlans and pvlans, they both get exported and zipped but when I import them into destination DVS the standard vlans get created but pvlans don't and fail with error below, so I understood that pvlans need different handling.

New-VDPortgroup : 2/9/2018 9:48:02 PM    New-VDPortgroup        Value cannot be null.

Parameter name: array   

At line:2 char:1

+ New-VDPortgroup -VDSwitch TST-DVS2 -Name “$($_.BaseName)_” -BackupPat ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [New-VDPortgroup], ViError

    + FullyQualifiedErrorId : Vds_Impl_VDPortGroupServiceImpl_RestoreVDPortGroup_Error,VMware.VimAutomation.Vds.Commands.Cmdlets.NewVDPortgroup

The lines below explain themselves, they import into destination DVS the standard vlans successfully.

#copy PGs to destination dVS

Get-ChildItem “C:\Users\Documents\DVS” | Foreach {

New-VDPortgroup -VDSwitch  TST-DVS2 -Name “$($_.BaseName)_” -BackupPath $_.FullName}

These lines grab the private vlans and write them directly into destination DVS successfully.

#copy PVLANs configs from source to destination dVS

Get-VDSwitch -Name  TST-DVS1 | Get-VDSwitchPrivateVlan | Foreach {

Get-VDSwitch -Name  TST-DVS2 | New-VDSwitchPrivateVlan -PrimaryVlanId $_.PrimaryVlanId -SecondaryVlanId $_.SecondaryVlanId -PrivateVlanType $_.PrivateVlanType}

Here I export only the private vlans zipped configs into a dedicated folder. However this step is of no use. Because I don't know how to import them. If I try manually by using the web client DVS option the action does not generate any error but the pvlan is not created. I believe it is because of duplicated pvlan portgroup name, which of course exist on the source DVS. I know this because if I perform the same manual action on a test DVS on a different vCenter the private vlans are created.

#copy PGs from source dVS

Get-VDSwitch -Name  TST-DVS1 | Get-VDPortgroup | where{$_.VlanConfiguration -match "PVLAN"} |

Foreach {

Export-VDPortGroup -VDPortGroup $_ -Description “Backup of $($_.Name) PG” -Destination “C:\Users\Documents\DVS\PVLAN\$($_.Name).Zip”}

I hope the rest of the thread makes more sense now.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Thanks, I'll play around with that over the weekend :smileycool:


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

LucD
Leadership
Leadership
Jump to solution

When I use my Set-dvSwPgVLAN function, I can assign the PVLANs to the portgroups.

I use a CSV to store the required info.

$srcVDS = 'vdsDEV01'

$tgtVDS = 'vdsDEV02'

$tempFolder = 'C:\Temp\VDS'

function Set-dVSwPgPVLAN{

    param($dvSw, $dvPgName, $pvlanNr)

   

    # Find the portgroup

    $dvSw.Portgroup | % {

       $dvPgTemp = Get-View -Id $_

       if($dvPgTemp.Name -eq $dvPgName){

         $dvPg = $dvPgTemp

       }

    }

   

    $spec = New-Object VMware.Vim.DVPortgroupConfigSpec

    $spec.defaultPortConfig = New-Object VMware.Vim.VMwareDVSPortSetting

    $spec.defaultPortConfig.vlan = New-Object VMware.Vim.VmwareDistributedVirtualSwitchPvlanSpec

    $spec.defaultPortConfig.vlan.pvlanId = $pvlanNr

   

    $dvPg.UpdateViewData()

    $spec.ConfigVersion = $dvPg.Config.ConfigVersion

   

    $taskMoRef = $dvPg.ReconfigureDVPortgroup_Task($spec)

   

    $task = Get-View $taskMoRef

    while("running","queued" -contains $task.Info.State){

        $task.UpdateViewData("Info")

    }

}

#copy PGs from source dVS 

Get-VDSwitch -Name $srcVDS | Get-VDPortgroup | where{$_.VlanConfiguration -notmatch "PVLAN" -and $_.Name -notmatch "DVUplinks"} | 

Foreach

    Export-VDPortGroup -VDPortGroup $_ -Description “Backup of $($_.Name) PG” -Destination $tempFolder\$($_.Name).Zip”

 

#copy PGs to destination dVS 

Get-ChildItem $tempFolder -Filter *.zip | Foreach

    New-VDPortgroup -VDSwitch $tgtVDS -Name $($_.BaseName)_” -BackupPath $_.FullName 

 

#copy PVLANs configs from source to destination dVS 

Get-VDSwitch -Name $srcVDS | Get-VDSwitchPrivateVlan | Foreach

    Get-VDSwitch -Name $tgtVDS |

    New-VDSwitchPrivateVlan -PrimaryVlanId $_.PrimaryVlanId -SecondaryVlanId $_.SecondaryVlanId -PrivateVlanType $_.PrivateVlanType 

 

#copy PGs from source dVS 

Get-VDSwitch -Name $srcVDS | Get-VDPortgroup | where{$_.VlanConfiguration -match "PVLAN"} | 

Select Name,@{N='VLANId';E={$_.VlanConfiguration.SecondaryVlanId}} |

Export-Csv -Path "$tempFolder\pvlan.csv" -NoTypeInformation -UseCulture

 

# Now import PVLAN zip files into dVS using Web Client

Import-Csv -Path "$tempFolder\pvlan.csv" -UseCulture | %{

    New-VDPortgroup -VDSwitch $tgtVDS -Name "$($_.Name)_"

    Set-dVSwPgPVLAN -dvSw (Get-VDSwitch -Name $tgtVDS).ExtensionData -dvPgName "$($_.Name)_" -pvlanNr $_.VLANId

}


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

zenivox
Hot Shot
Hot Shot
Jump to solution

Hi Luc, when you posted your solution I was working on extracting the data.xml of each PG from zip file using PowerShell and grab the seconday vlan id from there. You can imagine the text manipulation involved :smileylaugh: . When I saw this:

#copy PGs from source dVS

Get-VDSwitch -Name $srcVDS | Get-VDPortgroup | where{$_.VlanConfiguration -match "PVLAN"} |

Select Name,@{N='VLANId';E={$_.VlanConfiguration.SecondaryVlanId}} |

Export-Csv -Path "$tempFolder\pvlan.csv" -NoTypeInformation -UseCulture

I had a smile, as usual you come out with the simplest and cleanest solution!!

0 Kudos