Migrate Cisco Nexus 1000V to VDS with PowerShell

With the End of General Support (March 12, 2020) getting closer and closer I was asked to perform a migration and upgrade of a vSphere 6 environment. The plan was to install a new 6.7 VCSA and then migrate the hosts as-is to that new platform. After that the hosts could be upgraded to ESXi 6.7. So far so good but the current environment had Cisco 1000V distributed virtual switches so these had to go. The reason? Please read this FAQ: Discontinuation of third party vSwitch program.

At first I wanted to use the ‘Cisco Nexus 1000V to VMware VDS Migration Tool’ but I soon discovered that this tool was old and not maintained. I had several issues downloading and importing Python add-ins and although I managed to get the tool working, I didn’t have enough confidence to use this in a production environment.

So I decided to build my own tool in PowerShell based on the Python tool.
I started with the basic steps from the original tool:
⦁ Connection Details
⦁ Validate Migration
⦁ Create VDS
⦁ Migrate Host
⦁ Migrate Host Advanced
⦁ Migrate All
⦁ Remove VEM from host
⦁ Remove Nexus 1000V switch

Connection Details
The first function is Set-ConnectionDetails. In this function I ask for the user name and password for both vCenter and Cisco VSM. After connecting to vCenter and the VSM (Posh-SSH) I try to get some connection info from the VSM with the command “show svs connections”. After determining the connection status I retrieve the UUID in order to search for the Cisco DVS in vCenter. When it is found everything is ok and the function is finished.

Validate Migration
The second function is Validate-Migration. In this function the port profiles are collected with the command “show running-config port-profile” and saved in a text file for later use. I wanted to include some checks for unsupported features such as segmentation or LACP but I’m not sure how to incorporate those checks. So at the moment I will only save the port profiles as PortProfiles.txt.

Create VDS
This function is called Create-VDS and is used to create the VMware Distributed Switch with the necessary port groups based on the text file I saved in the previous function. This function contains magic!
The output of the command show running-config port-profile is one single string. But inside that string are values that I want to use such as the name of the profile, the description , and the VLAN id. To parse such a string is not so easy. But again, PowerShell to the rescue.

The ConvertFrom-String cmdlet extracts and parses structured properties from string content. This cmdlet generates an object by parsing text from a traditional text stream. For each string in the pipeline, the cmdlet splits the input by either a delimiter or a parse expression, and then assigns property names to each of the resulting split elements. You can provide these property names; if you do not, they are automatically generated for you.
The cmdlet’s default parameter set, ByDelimiter, splits exactly on the regular expression delimiter. It does not perform quote matching or delimiter escaping as the Import-Csv cmdlet does.
The cmdlet’s alternate parameter set, TemplateParsing, generates elements from the groups that are captured by a regular expression. For more information on regular expressions, see about_Regular_Expressions.
This cmdlet supports two modes: basic delimited parsing, and automatically-generated, example-driven parsing.
Delimited parsing, by default, splits the input at white space, and assigns property names to the resulting groups.
You can customize the delimiter by piping the ConvertFrom-String results into one of the Format-* cmdlets, or you can use the Delimiter parameter.
The cmdlet also supports automatically-generated, example-driven parsing based on the FlashExtract, research work by Microsoft Research.

So basically this is Machine Learning! You provide a template that looks like the string you want to parse and define the different properties you want returned. An example of such a template is shown here.

The first property I want to search for is called PortProfileName. The * is used for the first property. So when the second * comes along the cmdlet knows that is for the second set of properties. My second property is VLANs, the third is called Description and the last one is called PortGroupName.
Now when I parse the string with the command “gc PortProfiles.txt | ConvertFrom-String -TemplateContent $template” I get an object with properties that I can use later on.

So now I can do a foreach and use those properties to create the switch and portgroups.

Next time I will show you the other functions and the complete script. Till next time!