Showing posts with label Networking. Show all posts
Showing posts with label Networking. Show all posts

15 July 2018

Updated vNugglets.VDNetworking PowerShell module

Updated vNugglets PowerShell Module!Hurray -- the vNugglets.VDNetworking PowerShell module is now updated (with updates available on the PowerShellGallery)! This module has cmdlets for helping manage your VMware virtual distributed networking infrastructure, like reporting on and configuring traffic filtering/marking configurations. The ChangeLog has all of the juicy details, but the big news with this update:

The Set-VNVMHostNetworkAdapterVDUplink cmdlet provides the ability to manage the VDSwitch Uplink for a VMHost physical NIC ("VMNIC") on the VDSwitch of which the VMNIC is already a part -- finally! (this is not yet available in a native cmdlet in PowerCLI, but I'm sure that VMware has it on their list).

The copious examples show all kinds of ways to use this module.  Grab the module from the PowerShellGallery with the standard
Find-Module vNugglets.VDNetworking | Install-Module
that we all know and love (or, use Update-Module instead of Install-Module to update a previously installed version to current, of course).

Enjoy!

21 November 2013

Get VMs by Virtual Port Group with PowerCLI

How to find out what VMs use a particular virtual port group, and quickly?  Well, we have just the thing.  And, it also helps to illustrate the practical use of LinkedViews and the UpdateViewData() method of .NET View objects (about which we posted a while back in Even Faster PowerCLI Code with Get-View, UpdateViewData() and LinkedViews), along with the kind of speed increase that said method brings.

So, the function:
<#  .Description
    Function to get info about what VMs are on a virtual portgroup.  vNugglets, Oct 2013
    Highlights the use of the UpdateViewData() method of a .NET View object
    .Outputs
    PSObject
#>
function Get-VMOnNetworkPortGroup {
    param(
        ## name of network to get; regex pattern
        [parameter(Mandatory=$true)][string]$NetworkName_str
    ) ## end param

    ## get the .NET View objects for the network port groups whose label match the given name
    $arrNetworkViews = Get-View -ViewType Network -Property Name -Filter @{"Name" = $NetworkName_str}
    if (($arrNetworkViews | Measure-Object).Count -eq 0) {Write-Warning "No networks found matching name '$NetworkName_str'"; exit}

    ## get the networks' VMs' names, along with the name of the corresponding VMHost and cluster
    $arrNetworkViews | %{$_.UpdateViewData("Vm.Name","Vm.Runtime.Host.Name","Vm.Runtime.Host.Parent.Name")}
    ## create a new object for each VM on this network
    $arrNetworkViews | %{
        $viewNetwk = $_
        $viewNetwk.LinkedView.Vm | %{
            New-Object -TypeName PSObject -Property @{
                VMName = $_.Name
                NetworkName = $viewNetwk.Name
                VMHost = $_.Runtime.LinkedView.Host.Name
                Cluster = $_.Runtime.LinkedView.Host.LinkedView.Parent.Name
            } | Select-Object VMName,NetworkName,VMHost,Cluster
        } ## end foreach-object
    } ## end foreach-object
} ## end fn
And, some sample usage:
PS vN:\> Get-VMOnNetworkPortGroup -NetworkName "223|237"

VMName        NetworkName   VMHost           Cluster
------        -----------   ------           -------
dubuntu0      223.Prod      esxi01.dom.com   Cluster0
vma5          223.Prod      esxi02.dom.com   Cluster0
vcsa02        223.Prod      esxi02.dom.com   Cluster0
tmpl_test1    237.Dev       esxi12.dom.com   Cluster1
...
This illustrates the use of a regular expression pattern to match virtual networks whose names contain "223" or "237".

And, on the topic of speed increases:
## using standard cmdlets:
PS vN:\> Measure-Command {Get-VirtualPortGroup -Name SomeNetworkName | Get-VM | select name,@{n="VMHostName"; e={$_.VMHost.name}},@{n="ClusterName"; e={$_.VMHost.Parent.Name}}}
...
TotalSeconds      : 25.4870345


## using vNugglets function:
PS vN:\> Measure-Command {Get-VMOnNetworkPortGroup -NetworkName SomeNetworkName}
...
TotalSeconds      : 0.9676149      ## big winner!

So, while similar results can be had with native PowerCLI cmdlets, leveraging this function definitely comes in handy, especially when you are as impatient as we can be here at vNugglets.  Enjoy!

13 October 2013

Get VM by IP or MAC address via PowerCLI

I had need to get VMs based on IP, but, not particular IPs, just IPs in a certain subnet. Previously here on vNugglets we had a post about how to Find VM by NIC MAC Address. I have since added this logic to a function, and added the ability to get a VM by its IP address. With my recent need, I added another piece that allows for the IP address "wildcarding". The function, Get-VMByAddress, with its three ways to find a VM by IP- or MAC address:
function Get-VMByAddress {
    <#  .Description
        Find all VMs w/ a NIC w/ the given MAC address or IP address (by IP address relies on info returned from VMware Tools in the guest, so those must be installed).  Includes FindByIPWildcard, so that one can find VMs that approximate IP, like "10.0.0.*"
        .Example
        Get-VMByAddress -MAC 00:50:56:00:00:02
        VMName        MacAddress
        ------        ----------
        dev0-server   00:50:56:00:00:02,00:50:56:00:00:04

        Get VMs with given MAC address, return VM name and its MAC addresses
        .Example
        Get-VMByAddress -IP 10.37.31.120
        VMName         IPAddr
        ------         ------
        dev0-server2   192.168.133.1,192.168.253.1,10.37.31.120,fe80::...

        Get VMs with given IP as reported by Tools, return VM name and its IP addresses
        .Example
        Get-VMByAddress -AddressWildcard 10.0.0.*
        VMName   IPAddr
        ------   ------
        someVM0  10.0.0.119,fe80::...
        someVM2  10.0.0.138,fe80::...
        ...

        Get VMs matching the given wildcarded IP address
    #>

    [CmdletBinding(DefaultParametersetName="FindByMac")]
    param (
        ## MAC address in question, if finding VM by MAC; expects address in format "00:50:56:83:00:69"
        [parameter(Mandatory=$true,ParameterSetName="FindByMac")][string]$MacToFind_str,
        ## IP address in question, if finding VM by IP
        [parameter(Mandatory=$true,ParameterSetName="FindByIP")][ValidateScript({[bool][System.Net.IPAddress]::Parse($_)})][string]$IpToFind_str,
        ## wildcard string IP address (standard wildcards like "10.0.0.*"), if finding VM by approximate IP
        [parameter(Mandatory=$true,ParameterSetName="FindByIPWildcard")][string]$AddressWildcard_str
    ) ## end param


    Process {
        Switch ($PsCmdlet.ParameterSetName) {
            "FindByMac" {
                ## return the some info for the VM(s) with the NIC w/ the given MAC
                Get-View -Viewtype VirtualMachine -Property Name, Config.Hardware.Device | Where-Object {$_.Config.Hardware.Device | Where-Object {($_ -is [VMware.Vim.VirtualEthernetCard]) -and ($_.MacAddress -eq $MacToFind_str)}} | select @{n="VMName"; e={$_.Name}},@{n="MacAddress"; e={($_.Config.Hardware.Device | Where-Object {$_ -is [VMware.Vim.VirtualEthernetCard]} | %{$_.MacAddress} | sort) -join ","}}
                break;
                } ## end case
            {"FindByIp","FindByIPWildcard" -contains $_} {
                ## scriptblock to use for the Where clause in finding VMs
                $sblkFindByIP_WhereStatement = if ($PsCmdlet.ParameterSetName -eq "FindByIPWildcard") {{$_.IpAddress | Where-Object {$_ -like $AddressWildcard_str}}} else {{$_.IpAddress -contains $IpToFind_str}}
                ## return the .Net View object(s) for the VM(s) with the NIC(s) w/ the given IP
                Get-View -Viewtype VirtualMachine -Property Name, Guest.Net | Where-Object {$_.Guest.Net | Where-Object $sblkFindByIP_WhereStatement} | Select @{n="VMName"; e={$_.Name}}, @{n="IPAddr"; e={($_.Guest.Net | %{$_.IpAddress} | sort) -join ","}}
            } ## end case
        } ## end switch
    } ## end process
} ## end function

A few examples of using the function to find VMs by various addresses (as shown in the comment-based help, too):
PS vN:\> Get-VMByAddress -MAC 00:50:56:00:00:02
VMName        MacAddress
------        ----------
dev0-server   00:50:56:00:00:02,00:50:56:00:00:04


PS vN:\> Get-VMByAddress -IP 10.37.31.120
VMName         IPAddr
------         ------
dev0-server2   192.168.133.1,192.168.253.1,10.37.31.120,fe80::...


PS vN:\> Get-VMByAddress -AddressWildcard 10.0.0.*
VMName    IPAddr
------    ------
someVM0   10.0.0.119,fe80::...
someVM2   10.0.0.138,fe80::...
...

There are several places on the web that talk about getting VMs' IPs, getting their MAC addresses, exporting them, and so on, but this is for getting VMs based on the given address. Note: Since IP address info in vCenter is gotten from guest OSes via VMware Tools, this function is going to rely on that info. And, since the function uses everyone's favorite cmdlet, Get-View, and the calls with this cmdlet are properly tuned, you know that it is going to be FaF!

11 September 2011

Find VM by NIC MAC Address with PowerShell -- Fast Like!

There is the occasion on which it would be handy to find a VM based on a known MAC address. Say, for example, there is a duplicate IP address on the network, and the network team informs you of the offending MAC addresses. Unfortunately, there is not a simple/easy way to go about this.

There are some places on the web that discuss this topic, but none were satisfactory. Some were overly complex, storing objects and data without need. Others were written with the ease of writing being considered. While these will work, they do not suffice if the size of the environment is larger. Memory usage climbs in the PowerShell session, and the time-to-run grows far past what is necessary and desirable.

Yet another problem was the reliance of some scripts on VMware Tools to get the information. Granted, VMs would ideally have Tools current and running, but, we all know that in the real world, that just does not always happen.

So, we wrote a little nugglet that will get the VM(s) that have VirtualEthernetCard(s) with the given MAC address:
## Script function: find all VMs with one or more NIC with the given MAC address
## Author: vNugglets.com -- Aug 2011

## MAC addr of NIC(s) to find
$strMacToFind = "00:50:56:83:00:69"
## return the .NET View object(s) for the VM(s) with the NIC w/ the given MAC
Get-View -Viewtype VirtualMachine -Property Name, Config.Hardware.Device | ?{$_.Config.Hardware.Device | ?{($_ -is [VMware.Vim.VirtualEthernetCard]) -and ($_.MacAddress -eq $strMacToFind)}}

This is pretty straight forward to use: just set the variable for the MAC address to find, and then run the next line of code. This returns the .NET View object(s) for the VM(s) that have a NIC with the given MAC address. One could then do as they pleased with the objects.

To just report the info about the VM(s) with a NIC with the given MAC address, one could add a simple Select-Object statement. The following returns a list of matching VMs' names and their associated NICs' MAC addresses:
Get-View -Viewtype VirtualMachine -Property Name, Config.Hardware.Device | ?{$_.Config.Hardware.Device | `
?{($_ -is [VMware.Vim.VirtualEthernetCard]) -and ($_.MacAddress -eq $strMacToFind)}} | `
Select name, @{n="MAC(s)"; e={($_.Config.Hardware.Device | ?{($_ -is [VMware.Vim.VirtualEthernetCard])} | %{$_.MacAddress}) -join ","}}

The output would be something like:
Name     MAC(s)
----     ------
myVM     00:50:56:83:00:69,00:0c:29:00:08:01

PS C:\>

As for speed: this method of finding VMs with a given MAC address took around 25 seconds when run in a test environment of about 3200 VMs. Fast. Enjoy.

Update (30 Oct 2011 -- response to comment):
To use a similar technique to find a VMHost with a given MAC address, you can look at the Config.Network.Pnic property of a HostSystem .NET View object.  To find a VMHost with a given MAC, and quick like, use:
## to find a VMHost with given MAC address:
$strMacOfNICOnVMHostToFind = "00:0e:0c:00:00:01"

Get-View -ViewType HostSystem -Property Name, Config.Network.Pnic | ?{$_.Config.Network.Pnic | ?{$_.Mac -eq $strMacOfNICOnVMHostToFind}} | select Name, @{n="MAC(s)"; e={($_.Config.Network.Pnic | %{$_.Mac}) -join ","}}

The output is similar to the output above, but the Name will be of the given VMHost, and MAC(s) will be that host's MAC addresses. Enjoy, "Anonymous" commenter.

04 August 2011

Find Duplicate VM NIC MAC Addresses Using PowerShell

We were having issues with some VMs and their networking. Unexpected, unexplained things were happening, and eventually someone thought that there might be some duplicate MAC addresses in the mix, causing grief. Some of the VMs had been copied from other vCenters, among other things.

Side note by AC: the unique ID of a vCenter server helps dictate the range of assigned MAC addresses for VMs in that vCenter. Therefore, in order to avoid MAC address duplicates, one should ensure that no vCenters within the same network have the same unique ID.

So, to find if there were any duplicate MAC addresses in use by VM NICs, we whipped up the following:
## Script function: find duplicate MAC addresses, and list the VMs/addresses involved
## Author: vNugglets.com

## get VirtualMachine .NET views where the items is not marked as a Template
$colDevMacAddrInfo = `
Get-View -ViewType VirtualMachine -Property Name,Config.Hardware.Device -Filter @{"Config.Template" = "False"} | %{
$strVMName = $_.Name
$_.Config.Hardware.Device | Where-Object {$_ -is [VMware.Vim.VirtualEthernetCard]} | %{
New-Object -Type PSObject -Property @{VMName = $strVMName; MacAddr = $_.MacAddress}
} ## end foreach-object
} ## end foreach-object

## are all of the MAC addresses unique?
($colDevMacAddrInfo | Select-Object -unique MacAddr).Count -eq $colDevMacAddrInfo.Count

## get the non-unique MAC addresses, returning objects with the count of the duplicates, the duplicate MAC, and the VM names that have the duplicate MAC
$colDevMacAddrInfo | Group-Object MacAddr | Where-Object {$_.count -gt 1} | Select-Object Count,@{n="DuplicateMAC"; e={$_.Name}},@{n="VMNames"; e={($_.Group | %{$_.VMName}) -join ","}}

It uses the Get-View cmdlet with the -Property parameter to ensure minimum memory usage and maximum speed.

Line 14: quick check to determine if there are any duplicate MAC addresses present -- compares the count of unique addresses to the total count of addresses

If there are duplicate MAC addresses, line 17 returns some nice information about the given MAC address, the count of VM NICs that have it, and the names of the VMs involved.

Once one finds the offending VMs, they can use something like the script in the vNugglets post Setting MAC Address for VM NICs using PowerShell to change the necessary MAC addresses and return things to standard working order. Hurray!

25 July 2011

Setting MAC Address for VM NICs using PowerShell

A bit ago, there were some questions in the VMware VMTN community forums about setting explicit MAC addresses for VMs' NICs.

While this can be done via PowerCLI using the Set-NetworkAdapter cmdlet, the MAC address range is restricted to 00:50:56:00:00:00 - 00:50:56:3F:FF:FF when using the cmdlet, which is only a subset of the range that VMware uses.

An example came up where one might need to set the MAC address to something in a valid VMware range (with VMware OUIs like "00:50:56" or "00:0C:29") outside of the subset above. This can be done using the Web Services API, as it does not have the same range limitation as the cmdlet. The well-commented code below shows how to do so using the API:

## script function:  set the MAC address of a VM's NIC
## Author: vNugglets.com

## the name of the VM whose NIC's MAC address to change
$strTargetVMName = "myVM01"
## the MAC address to use
$strNewMACAddr = "00:50:56:90:00:01"

## get the .NET view object of the VM
$viewTargetVM = Get-View -ViewType VirtualMachine -Property Name,Config.Hardware.Device -Filter @{"Name" = "^${strTargetVMName}$"}
## get the NIC device (further operations assume that this VM has only one NIC)
$deviceNIC = $viewTargetVM.Config.Hardware.Device | Where-Object {$_ -is [VMware.Vim.VirtualEthernetCard]}
## set the MAC address to the specified value
$deviceNIC.MacAddress = $strNewMACAddr
## set the MAC address type to manual
$deviceNIC.addressType = "Manual"

## create the new VMConfigSpec
$specNewVMConfig = New-Object VMware.Vim.VirtualMachineConfigSpec -Property @{
   ## setup the deviceChange object
   deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec -Property @{
       ## the kind of operation, from the given enumeration
       operation = "edit"
       ## the device to change, with the desired settings
       device = $deviceNIC
   } ## end New-Object
} ## end New-Object

## reconfigure the "clone" VM
$viewTargetVM.ReconfigVM($specNewVMConfig)


The ReconfigVM() method does not care if the new MAC address is a valid VMware MAC address. It does not even seem to care if the new MAC address string is a valid hex MAC address. So, use with care -- one would not want to break networking on their precious VM by setting its NIC to have an invalid MAC address, or a duplicate, etc.

Other info: the valid VMware OUIs can be found many places, like at the IEEE.org Public Listing search site.


Update 25 Nov 2011:
Do note that changing the MAC address of a VM NIC to something outside of the "accepted" range will cause other PowerCLI cmdlets and the vSphere client to report that the NIC's MAC is "not in the valid range", and may prevent further operations on that VM's NIC with those tools.  Thank-you to the anonymous commenter here and to LucD (in the VMware Communities thread at http://communities.vmware.com/message/1869800#1869800) for highlighting this point.


Update 31 Dec 2011:
The -Filter parameter for the Get-View call on line 10 was using a regular expression that had the possibility of returning more than one VM View object.  I have updated the regular expression to only match VMs of exactly the given name.  Thanks go to Joep Piscaer for pointing out the issue.  The code in this post has been updated.

23 December 2009

Find Busted VMNICs

So, while we mentioned this would be a "low-volume blog", we didn't think we'd get our domain expiration notice before the first vNugglet hatched. Anyway, a problem we've run into in the past are VMNICs that suddenly have no link for whatever reason--switch upgrades, random user error, etc.

The following script will search the connected vCenter Server(s) to find any VMNICs that are actively being used in a standard vSwitch and also have no link (0Mbps).

## Script function: Lists all VMNICs that have no link and that are connected to a vSwitch (sorted by corresponding host).
## Author: vNugglets.com
## Usage: Connect to vCenter, run script interactively.


## Get all hosts and sort by name
Get-VMHost | Sort-Object -Property Name | ForEach-Object {
## (Re)Initialize array of failed VMNICs
$arrFailedVMNICsInUse = @()

## Get current host's Name, NICs, and vSwitches objects
$objCurrentHostNICs = Get-VMHostNetworkAdapter -VMHost $_
$objCurrentHostVSwitches = Get-VirtualSwitch -VMHost $_

## For each failed NIC, if it is attached to a vSwitch, add it to the failed VMNICs array
$objCurrentHostNICs | Where-Object {$_.BitRatePerSec -eq 0} | ForEach-Object {
$objCurrentFailedNIC = $_
$arrValidVMNICs = $objCurrentHostVSwitches | ForEach-Object {$_.Nic}
if ($arrValidVMNICs -match $objCurrentFailedNIC.DeviceName) {
$arrFailedVMNICsInUse += $objCurrentFailedNIC
} ## end if
} ## end inner ForEach-Object

## If there is at least one failed VMNIC, display the hostname it is associated with followed by the list of failed VMNICs
if ($arrFailedVMNICsInUse.Count -gt 0) {
$_.Name + ":"
$arrFailedVMNICsInUse | ForEach-Object {
"`t" + $_.DeviceName
} ## end ForEach-Object
Write-Host ""
} ## end if
} ## end outer ForEach-Object

That's it! Hopefully this is helpful to someone else.


*UPDATE - 19 January 2011: Updated script due to the following properties that are now deprecated.

PS C:\> .\findBustedVMnics.ps1
WARNING: 'PhysicalNic' property is obsolete. Use 'Get-VMHostNetworkAdapter' cmdlet instead.
WARNING: 'VirtualSwitch' property is obsolete. Use 'Get-VirtualSwitch' cmdlet instead.

...