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.
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
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
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
Let me know if it gets you somewhere, otherwise I can lend a hand.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
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
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
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.
Also when you use the Server parameter, explicitly referencing to the vCenter?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
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
No, I mean to use the actual cmdlet Get-VDSwitch, not my function.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
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.
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
I already got that part in my initial script at the section:
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.
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
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.
Thanks, I'll play around with that over the weekend :smileycool:
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
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
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!!