Script Extracts and Examples (PowerCLI): Difference between revisions

From vwiki
Jump to navigation Jump to search
(→‎ESX Log Tail: Added note)
m (Typo fix)
 
(40 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Getting Started ==
#REDIRECT [[:Category:PowerCLI]]
Before being able to use any the following script you need to install...
* [http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx Windows PowerShell V1]
* [http://support.microsoft.com/kb/968929 Windows Powershell V2]
* [http://www.vmware.com/go/powershell VI Toolkit]
 
On the first run you need to allow the Toolkit to run properly by running (you need to run this command as an administrator, so if you're using Windows 7, for example, you'll need to start the Powershell console as an administrator, regardless of whether you're currently logged in as an admin)...
<source lang="powershell"> Set-ExecutionPolicy RemoteSigned </source>
 
Connect to the Virtual Centre (or ESX) server using the following command using your normal username and password (same as you'd use to log into the VI Client).  You will need access to the servers on TCP 443.
<source lang="powershell"> Connect-VIServer -Server <server> -User <user> -Password <pass> </source>
 
Once connected you can do real work with the PowerCLI, to see what's available, login to https://server/mob.  This is effectively where you end up once you've completed the <code> Connect-VIServer </code> command.
 
Be aware that PowerShell commands generally return objects, rather than text, and that the textual representation of the return object is often abbreviated for simplicity.  To see the entire return for a command, pipe the result into <code>Format-List</code>.  To complicate matters further, some return objects contain further objects, see examples below
 
<source lang="powershell">
[vSphere PowerCLI] E:\> get-vm -name "vserver1"
 
Name                PowerState Num CPUs Memory (MB)
----                ---------- -------- -----------
vserver1              PoweredOn  1        756
 
 
[vSphere PowerCLI] E:\> get-vm -name "vserver1" | Format-List *
 
PowerState          : PoweredOn
Description        :
Guest              : VMware.VimAutomation.Client20.VMGuestImpl
NumCpu              : 1
MemoryMB            : 756
CDDrives            : {CD/DVD Drive 1}
FloppyDrives        : {Floppy Drive 1}
HardDisks          : {Hard Disk 1}
NetworkAdapters    : {Network Adapter 1}
Host                : esx1.domain.com
HostId              : HostSystem-host-301
HARestartPriority  : ClusterRestartPriority
HAIsolationResponse : AsSpecifiedByCluster
DrsAutomationLevel  : AsSpecifiedByCluster
CustomFields        : {}
Id                  : VirtualMachine-vm-25136
Name                : vserver1
 
 
[vSphere PowerCLI] E:\> get-vm -name "vserver2" | Format-List *
 
PowerState          : PoweredOff
Description        :
Guest              : VMware.VimAutomation.Client20.VMGuestImpl
NumCpu              : 2
MemoryMB            : 2048
CDDrives            : {CD/DVD Drive 1}
FloppyDrives        : {Floppy Drive 1}
HardDisks          : {Hard Disk 1}
NetworkAdapters    : {Network Adapter 1, Network Adapter 2, Network Adapter 3}
Host                : vserver2.domain.com
HostId              : HostSystem-host-662
HARestartPriority  : ClusterRestartPriority
HAIsolationResponse : AsSpecifiedByCluster
DrsAutomationLevel  : AsSpecifiedByCluster
CustomFields        : {}
Id                  : VirtualMachine-vm-697
Name                : vserver2
 
 
[vSphere PowerCLI] E:\> get-vm -name "vserver2" | ForEach-Object {$_.NetworkAdapters}
 
MacAddress      : 00:50:AB:CD:40:59
WakeOnLanEnabled : True
NetworkName      : Some_Network
Type            : Flexible
ConnectionState  : VMware.VimAutomation.Client20.ConnectInfoImpl
Id              : VirtualMachine-vm-697/4000
Name            : Network Adapter 1
 
MacAddress      : 00:50:AB:CD:55:40
WakeOnLanEnabled : True
NetworkName      : Another_Network
Type            : Flexible
ConnectionState  : VMware.VimAutomation.Client20.ConnectInfoImpl
Id              : VirtualMachine-vm-697/4001
Name            : Network Adapter 2
 
MacAddress      : 00:50:AB:CD:56:da
WakeOnLanEnabled : True
NetworkName      : Yet_Another_Network
Type            : Flexible
ConnectionState  : VMware.VimAutomation.Client20.ConnectInfoImpl
Id              : VirtualMachine-vm-697/4002
Name            : Network Adapter 3
</source>
 
=== Installed Version ===
To determine the version of PowerCLI currently installed use;
* <code> Get-PowerCLIversion </code>
 
=== Scheduling ===
To schedule a script to run you need to include the PowerCLI VIM console file so that PowerCLI Cmd-lets are available to your script.  The command should use the following structure...
* <code> Powershell.exe -PSConsoleFile <vim.psc1> &<script.ps1> </code>
 
For example, on a WinXP or Win2k3 (32bit) machine you might have something like...
* <code> C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe -PSConsoleFile "C:\Program Files\VMware\Infrastructure\vSphere PowerCLI\vim.psc1" "& C:\Scripts\ESX-probe.ps1" </code>
Or on a Win7 or Win2k8 (64bit) machine you might have something like...
* <code> Powershell -PSConsoleFile "C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\vim.psc1" "& C:\Scripts\ESX-probe.ps1" </code>
 
== Useful CmdLets etc ==
=== Virtual Machine ===
 
{|cellpadding="2" cellspacing="0" border="1"
! Command    !! Description
|-
| <code> Get-VM </code>
| Get list of VM's
|-
| <code> Get-VM <nowiki>|</nowiki> Sort -Property Name </code>
| Get list of VM's, sorted by name
|-
| <code> Get-VM -Name MyVM -Location (Get-Folder -Name "MyFolder") </code>
| Get VM within a specific folder (for when you've VM's with identical names if different folders)
|-
| <code> Get-VMGuest -VM (get-vm -name MyVM) </code>
| Get VM guest info (IP address, OS)
|-
| <code> Get-VM MyVM <nowiki>|</nowiki> %{(Get-View $_.Id).config.uuid} </code>
| Get VM's UUID
|-
| <code> Get-VM MyVM <nowiki>|</nowiki> Move-VM -datastore (Get-datastore "DestinationDatastore") </code>
| Storage VMotion
|-
| <code> Shutdown-VMGuest -VM (get-vm -name "vserver1") </code>
| Sends OS shutdown command via VM Tools
|-
| <code> get-VM MyVM <nowiki>|</nowiki> Get-VIEvent <nowiki>|</nowiki> Where {$_.fullFormattedMessage -like "*Power*"} </code>
| Get Power On/Off events for VM
|-
| <code> Get-VM MyVM <nowiki>|</nowiki> Get-Snapshot <nowiki>|</nowiki> Select-Object -Property Name, Description, Created, SizeMB <nowiki>|</nowiki> Format-List * </code>
| Get Snapshot info for a VM
|}
 
=== ESX Host ===
{|cellpadding="2" cellspacing="0" border="1"
! Command    !! Description
|-
| <code> get-vmhost -name MyESX* <nowiki>|</nowiki> %{(Get-View $_.ID).Config.Product} </code>
| Get ESX software version (inc build no)
|-
| <code> Get-VMHost MyESX* <nowiki>|</nowiki> Get-VirtualPortGroup <nowiki>|</nowiki> Sort VLanId <nowiki>|</nowiki> Select VLanId, Name </code>
| Get VLANs configured on ESX
|-
| <code> Get-ScsiLun -VMHost MyESX* -LunType disk </code>
| Get ESX disk VML ID's (SAN ID are a part of the VML - useful for identifying LUN's with SAN team). See [[ESX#SAN_LUN_ID|ESX SAN LUN ID]]
|-
| <code> Get-ScsiLun -VMHost MyESX* -LunType disk <nowiki>|</nowiki> Get-ScsiLunPath </code>
| Get ESX SCSI paths info
|-
| <code> Get-VMHostHba -VMHost MyESX* <nowiki>|</nowiki> Where {$_.Type -eq "FibreChannel"} <nowiki>|</nowiki> Format-List * </code>
| Get ESX Fibre Channel HBA info
|}
 
Get-VMHost MyESX* <nowiki>|</nowiki> Get-VirtualPortGroup <nowiki>|</nowiki> Sort VLanId <nowiki>|</nowiki> Select VLanId, Name
 
=== ESXi Logs ===
{|cellpadding="2" cellspacing="0" border="1"
! Command    !! Description
|-
| <code> Get-Log -VMHost (Get-VMHost "MyESX*") -Bundle -DestinationPath C:\Users\name </code>
| Generate diagnostic bundle
|-
| <code> Get-Log vpxa -VMHost (Get-VMHost "MyESX*") <nowiki>|</nowiki> Select -ExpandProperty Entries </code>
| Get vpxa log
|-
| <code> Get-Log messages -VMHost (Get-VMHost "MyESX*") <nowiki>|</nowiki> Select -ExpandProperty Entries </code>
| Get messages log
|-
| <code> Get-Log hostd -VMHost (Get-VMHost "MyESX*") -StartLineNum 1000 -NumLines 100 <nowiki>|</nowiki> Select -ExpandProperty Entries </code>
| Get hostd log from line 1000
|-
| <code> Get-Log hostd -VMHost (Get-VMHost "MyESX*") <nowiki>|</nowiki> Select -Expand Entries <nowiki>|</nowiki> Select-String FindMe </code>
| Get hostd log entries that include FindMe
|-
| <code> Get-Log hostd -VMHost (Get-VMHost "MyESX*") <nowiki>|</nowiki> Select -Expand Entries <nowiki>|</nowiki> Out-GridView </code>
| '''Dump hostd log into GridView'''
|}
 
=== Storage ===
{|cellpadding="2" cellspacing="0" border="1"
! Command    !! Description
|-
| <code> get-vm -name "MyVM" <nowiki>|</nowiki> get-harddisk <nowiki>|</nowiki> Format-List </code>
| Get the vHD details for a particular VM
|-
| <code> (Get-VM -name "MyVM" <nowiki>|</nowiki> Get-VMGuest).Disks </code>
| Get the HD details for a particular VM (as seen from within guest OS)
|-
| <code> get-vm -Location (Get-Folder -Name "MyFolder") <nowiki>|</nowiki> get-harddisk <nowiki>|</nowiki> sort-object -Property Filename </code>
| Get the vHD details for all VM’s in a folder (sorted by VMDK path)
|-
| <code> New-PSDrive -Name DS -PSProvider ViMdatastore -Root '\' -location (Get-Datastore MyDatastore) </code>
| Create a PowerShell drive for the ''MyDatastore'' datastore
|-
| <code> Copy-DatastoreItem C:\Temp\FileToUpload.vmdk -Destination DS:\VMFolder\ </code>
| Upload file to datastore (a PowerShell drive needs to be create 1st - see above)
|}
 
== Performance Statistics ==
The full wealth of performance metrics that are collated by virtual centre are available via the PowerCLI.  This can be very useful for creating custom reports, feeding data into other tools etc.
 
It's important to understand how ESX's generate and manage performance data before going any further...
# An ESX collects performance metrics every 20 sec (know as the Realtime interval), this is retained on the server for 1 hour.
# The ESX rolls the Realtime data up into 5 min interval data
#* [Stand-alone ESX] This 5 min data is retained for 1 day
#* [VC managed ESX] The data is uploaded to the VC database
 
Once in the Virtual Centre database, the data is then rolled up into Historical Interval tables via SQL jobs...
* 5 min interval, 1 day retention
* 30 min interval, 1 week retention
* 2 hr interval, 1 month retention
* 1 day interval, 1 year retention
 
Note that the following are configurable (to a varying degree) via the VI Client.
* The VC rollup intervals and retention periods
* The statistics depth (typically certain metrics are discarded as the retention period grows)
 
To see the available intervals for which metrics are available, use the following command (the results will vary depending on whether you're connected to an ESX or a Virtual Centre).
<source lang="powershell">[vSphere PowerCLI] E:\> Get-StatInterval
 
Name                          SamplingPeriodSecs          StorageTimeSecs Client
----                          ------------------          --------------- ------
Past Day                                      300                    86400 VMware.VimAutomation....
Past Week                                    1800                  604800 VMware.VimAutomation....
Past Month                                  7200                  2592000 VMware.VimAutomation....
Past Year                                  86400                31536000 VMware.VimAutomation....</source>
 
=== Available Metrics ===
Metrics are available for all objects you'd expect (and probably more), not limited to the following...
* Virtual Machines
* Virtual machines Hosts (ESX's)
* Resource Pools
* Datastores
 
For a full list of what objects have what performance counters, and what those counters mean see http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.PerformanceManager.html. 
 
The easiest way to ascertain what metric is available for what object is to use Get-StatType...
<source lang="powershell">[vSphere PowerCLI] E:\> Get-VM "vm-server" | Get-StatType
cpu.usage.average
cpu.usagemhz.average
mem.usage.average
mem.granted.average
mem.active.average
...
 
[vSphere PowerCLI] E:\> Get-VMHost "esx-server*" | Get-StatType
cpu.usage.average
cpu.usagemhz.average
mem.usage.average
mem.granted.average
mem.active.average
mem.shared.average
mem.zero.average
mem.unreserved.average
...</source>
 
'''In order to determine which sampling periods are available''', you need to use the '''<code> Get-StatInterval </code>''' command.  Remember that there is also the '''Realtime''' interval, at which all metrics are available.  The results depend on whether you're connected to a Virtual Centre (and how its configured) or an ESX (and whether that's being managed by a VC)...
<source lang="powershell">
[vSphere PowerCLI] E:\> Get-StatInterval
 
Name                          SamplingPeriodSecs          StorageTimeSecs Client
----                          ------------------          --------------- ------
Past Day                                      300                    86400 VMware.VimAutomation....
Past Week                                    1800                  604800 VMware.VimAutomation....
Past Month                                  7200                  2592000 VMware.VimAutomation....
Past Year                                  86400                31536000 VMware.VimAutomation....
</source>
 
However, just because a metric is available, doesn't make it available in the interval you'd like.  '''In order to find out whether a statistic is available in the interval you'd like''', you need to use the '''<code> Get-StatType -Interval <secs/name> </code>'''...
 
<source lang="powershell">
[vSphere PowerCLI] E:\> Get-VMHost "esx-server*" | Get-Stat -MaxSamples 5 -IntervalSecs 300
 
 
MetricId                  Timestamp                                Value Unit
---------                ----------                              ----- ----
cpu.usage.average        19/01/2010 09:15:00                      7.64 %
cpu.usage.average        19/01/2010 09:10:00                        6.5 %
cpu.usage.average        19/01/2010 09:05:00                      6.37 %
cpu.usage.average        19/01/2010 09:00:00                      6.39 %
cpu.usage.average        19/01/2010 08:55:00                      6.35 %
cpu.usagemhz.average      19/01/2010 09:15:00                        813 MHz
cpu.usagemhz.average      19/01/2010 09:10:00                        692 MHz
cpu.usagemhz.average      19/01/2010 09:05:00                        678 MHz
cpu.usagemhz.average      19/01/2010 09:00:00                        680 MHz
cpu.usagemhz.average      19/01/2010 08:55:00                        676 MHz
mem.usage.average        19/01/2010 09:15:00                      24.89 %
mem.usage.average        19/01/2010 09:10:00                      24.88 %
mem.usage.average        19/01/2010 09:05:00                      24.89 %
mem.usage.average        19/01/2010 09:00:00                      24.9 %
mem.usage.average        19/01/2010 08:55:00                      24.91 %
disk.usage.average        19/01/2010 09:15:00                        156 KBps
disk.usage.average        19/01/2010 09:10:00                        124 KBps
disk.usage.average        19/01/2010 09:05:00                        131 KBps
disk.usage.average        19/01/2010 09:00:00                        126 KBps
disk.usage.average        19/01/2010 08:55:00                        136 KBps
net.usage.average        19/01/2010 09:15:00                          7 KBps
net.usage.average        19/01/2010 09:10:00                          8 KBps
net.usage.average        19/01/2010 09:05:00                          7 KBps
net.usage.average        19/01/2010 09:00:00                          7 KBps
net.usage.average        19/01/2010 08:55:00                          7 KBps
sys.uptime.latest        19/01/2010 09:15:00                    5173577 second
sys.uptime.latest        19/01/2010 09:10:00                    5173277 second
sys.uptime.latest        19/01/2010 09:05:00                    5172977 second
sys.uptime.latest        19/01/2010 09:00:00                    5172677 second
sys.uptime.latest        19/01/2010 08:55:00                    5172376 second
</source>
 
A couple of final points to note
* To retrieve data for the Realtime interval, use the <code> -Realtime </code> option, not <code> -IntervalSecs 20 </code>
** All Realtime metrics are averages (as they're an average over the sampling period)
* Virtual Centre generally drops metrics during roll-ups etc (subject to configuration), therefore for the fullest range of metrics, use the Realtime interval.
** I'd suggest always trying to go via the Virtual Centre, but the data you're after isn't available, check with the ESX direct.
* Be careful when retrieving metrics that might have multiple instances (eg CPU), this is relatively obvious in vSphere as it'll show an instance column, not so in VI3.  You can filter so as to see, for example, only the aggregate instance
** <source lang="powershell">get-vmhost "esx-server*" | get-stat -Stat cpu.usage.average -MaxSamples 1 -Realtime | Where{$_.Instance -eq ""}</source>
 
== Script Extracts ==
=== VM's with Datastores List ===
List of Virtual Machines, and their datastores (with usage)
<source lang="powershell">
$datastoreExp = @{N="Datastore"; E={ ($_ | get-datastore | select-object -first 1).Name }}
$diskSizeExp = @{N="Total Disk"; E={ ($_ | get-harddisk | measure-object -property CapacityKB -sum).Sum }}
get-vm | select Name, $datastoreExp, $diskSizeExp | sort -property Datastore,"Total Disk"
</source>
 
=== VM's with Host and Cluster List ===
<source lang="powershell">
$vms = Get-VM | sort -property Name
foreach ($vm in $vms)
{
    $vm | Get-Cluster | Select-Object @{Name="VM"; Expression={$vm.name}},@{Name="Current Host"; Expression={$vm.host}},Name
}
</source>
 
=== VM's Inventory CSV ===
 
<source lang="powershell">
$start = Get-Date
 
# Create table for output
# Name DC OS UUID IP Cluster ESX's
 
$table = New-Object system.Data.DataTable "Results"
 
$col1 = New-Object system.Data.DataColumn Name,([string])
$col2 = New-Object system.Data.DataColumn DC,([string])
$col3 = New-Object system.Data.DataColumn OS,([string])
$col4 = New-Object system.Data.DataColumn UUID,([string])
$col5 = New-Object system.Data.DataColumn MgmtIP,([string])
$col6 = New-Object system.Data.DataColumn Cluster,([string])
#$col7 = New-Object system.Data.DataColumn ESXs,([string])
 
$table.columns.add($col1)
$table.columns.add($col2)
$table.columns.add($col3)
$table.columns.add($col4)
$table.columns.add($col5)
$table.columns.add($col6)
#$table.columns.add($col7)
 
$duration = (New-TimeSpan $start (Get-Date)).TotalSeconds
"Created table after $duration secs"
 
# Get VMs object
$vms = Get-VM | Sort -property Name
 
$duration = (New-TimeSpan $start (Get-Date)).TotalSeconds
"Got object list of VM's after $duration secs"
 
foreach ($vm in $vms)
{
$row = $table.NewRow()
$row.Name = (Get-VM -Name $vm).Name
$row.DC = (Get-Datacenter -VM $vm).Name
$row.OS = (Get-VMGuest -VM $vm).OSFullName
$row.UUID = %{(Get-View $vm.Id).config.uuid}
$row.MgmtIP =  [string]::join(" ", ((Get-VMGuest -VM $vm).IPAddress)) # Need to join potential list of IP's
$row.Cluster = (Get-Cluster -VM $vm).Name
$table.Rows.Add($row)
"Added row for $vm"
}
 
$duration = (New-TimeSpan $start (Get-Date)).TotalSeconds
"Populated table after $duration secs"
 
$table | Format-Table
$table | Export-Csv -path result.csv
</source>
 
=== VM Storage Usage ===
'''Total''' storage usage (including any snapshots, logs, etc, etc), not just the VMDK files.
Adapted from post by Arnim van Lieshout http://www.van-lieshout.com/2009/07/how-big-is-my-vm/
 
<source lang="powershell">
function Get-VMDiskUsage($vm2do)
{
    #Initialize variables
    $VMDirs =@()
    $VMSize = 0
 
    $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
    $searchSpec.details = New-Object VMware.Vim.FileQueryFlags
    $searchSpec.details.fileSize = $TRUE
 
    Get-View -VIObject $vm2do | % {
        #Create an array with the vm's directories
        $VMDirs += $_.Config.Files.VmPathName.split("/")[0]
        $VMDirs += $_.Config.Files.SnapshotDirectory.split("/")[0]
        $VMDirs += $_.Config.Files.SuspendDirectory.split("/")[0]
        $VMDirs += $_.Config.Files.LogDirectory.split("/")[0]
        #Add directories of the vm's virtual disk files
        foreach ($disk in $_.Layout.Disk) {
            foreach ($diskfile in $disk.diskfile){
                $VMDirs += $diskfile.split("/")[0]
            }
        }
        #Only take unique array items
        $VMDirs = $VMDirs | Sort | Get-Unique
 
        foreach ($dir in $VMDirs){
            $ds = Get-Datastore ($dir.split("[")[1]).split("]")[0]
            $dsb = Get-View (($ds | get-view).Browser)
            $taskMoRef  = $dsb.SearchDatastoreSubFolders_Task($dir,$searchSpec)
            $task = Get-View $taskMoRef
 
            while($task.Info.State -eq "running" -or $task.Info.State -eq "queued"){$task = Get-View $taskMoRef }
            foreach ($result in $task.Info.Result){
                foreach ($file in $result.File){
                    $VMSize += $file.FileSize
                }
            }
        }
    }
 
    # VM disk usage in GB
    $VMSize/1048576000
}
Get-VMDiskUsage (Get-VM "MyVM")
</source>
 
=== VM's with Snapshots Running ===
 
<source lang="powershell">
$OutputFile = "VM-Snapshot.csv"
 
function Log ($text) {
    [int]$duration = (New-TimeSpan $start (Get-Date)).TotalSeconds
    Write-Host "$duration secs | $text"
}
 
function Log-NoNewLine ($text) {
    [int]$duration = (New-TimeSpan $start (Get-Date)).TotalSeconds
    Write-Host "$duration secs | $text" -nonewline
}
 
$start = Get-Date
 
$table = New-Object system.Data.DataTable "Results"
$table.columns.add((New-Object system.Data.DataColumn Name,([string])))
$table.columns.add((New-Object system.Data.DataColumn Folder,([string])))
$table.columns.add((New-Object system.Data.DataColumn Snap,([string])))
$table.columns.add((New-Object system.Data.DataColumn Created,([datetime])))
$table.columns.add((New-Object system.Data.DataColumn Size_MB,([single])))
$table.columns.add((New-Object system.Data.DataColumn PowerState,([string])))
 
Log("Getting list of VMs to check...")
$VMs = Get-VM | Where {$_.PowerState -eq "PoweredOn"} | Sort -Property Name
Log ("Got list of " + ($VMs.Count) + " VMs to check")
 
$VMno = 0
$VMtot = $VMs.Count
 
foreach ($vm in $VMs) {
    $VMno = $VMno + 1
    Log-NoNewLine "[$VMno/$VMtot] $vm - "
   
    $Snaps = Get-Snapshot -VM $vm
    if ($Snaps) {
        foreach ($snap in $snaps) {
            $row = $table.NewRow()
            $row.Name = $vm.Name
            $row.Folder = Get-Folder -Id $vm.FolderId
            $row.Snap = $snap.Name
            $row.Created = $snap.Created
            $row.Size_MB = $snap.SizeMB
            $row.PowerState = $snap.PowerState
            Write-Host $row.Snap "| Created" $row.Created "| Size" $row.Size_MB "MB | " $row.PowerState
        }
    } else {
        Write-Host "No snapshot"
    }
}
 
if ($table.rows.Count) {
    Log "Completed, writing out table..."
   
    $table | Format-Table
    $table | Export-Csv -path $OutputFile
   
    #Send via email
    $smtp = New-Object Net.Mail.SmtpClient -arg "smtpserver"
    $msg = New-Object Net.Mail.MailMessage
    $attach = New-Object Net.Mail.Attachment($OutputFile)
   
    $msg.From = "from"
    $msg.To.Add = "to"
    $msg.Subject = "Snapshots found running!!"
    $msg.Body = "$table.rows.Count snapshots found to be running, see attachment for further info"
   
    $smtp.Send($msg)
    $attach.Dispose()
}
 
Log "Completed!"
</source>
 
=== VM's Effective CPU Shares ===
Calculates the effective relative CPU shares of VM's contained within resource pools.  Can only handle resource pool depth of 1.
 
<source lang="powershell">
function Log ($text) {
    [int]$duration = (New-TimeSpan $start (Get-Date)).TotalSeconds
    Write-Host "$duration secs | $text"
}
$start = Get-Date
 
Log "Initialising output tables..."
 
$tSummary = New-Object system.Data.DataTable "Summary Results"
$tSummary.columns.add((New-Object system.Data.DataColumn Name,([string])))
$tSummary.columns.add((New-Object system.Data.DataColumn CPU_Shares,([int])))
$tSummary.columns.add((New-Object system.Data.DataColumn VMs,([int])))
$tSummary.columns.add((New-Object system.Data.DataColumn Weighted,([single])))
 
$tDetail = New-Object system.Data.DataTable "Detailed Results"
$tDetail.columns.add((New-Object system.Data.DataColumn Res_Pool,([string])))
$tDetail.columns.add((New-Object system.Data.DataColumn VM,([string])))
$tDetail.columns.add((New-Object system.Data.DataColumn Res_CPU_Shares,([int])))
$tDetail.columns.add((New-Object system.Data.DataColumn VM_CPU_Shares,([int])))
$tDetail.columns.add((New-Object system.Data.DataColumn Eff_VM_Shares,([single])))
 
Log "Getting resource pools..."
$ResPools = Get-ResourcePool
 
ForEach ($ResPool in $ResPools) {
    $VMs = Get-VM -Location $ResPool -NoRecursion | Where {$_.PowerState -eq "PoweredOn"}
    If (!$VMs) {        #Skip any resource pools with no VM's
        Log ("Skipping " + $ResPool.Name + " (no VMs)")
        Continue
    }
    $rSummary = $tSummary.NewRow()
   
    Log ("Analysing " + $ResPool.Name + "...")
    $rSummary.Name = $ResPool.Name
    $rSummary.CPU_Shares = $ResPool.NumCpuShares
   
    If (!$VMs.Count) {  # If only 1 VM in ResPool we don't get a normal array returned (so !VMs.Count is NULL)
        $rSummary.VMs = 1
    } else {
        $rSummary.VMs = $VMs.Count
    }
    $rSummary.Weighted = $rSummary.CPU_Shares / $rSummary.VMs
    $tSummary.Rows.Add($rSummary)
   
    # Get each VM's shares
    $totShares = 0
    $VMshares = @{}
    ForEach ($vm in $VMs) {
        $VMShares[$vm.Name] = ($vm | Get-VMResourceConfiguration).NumCpuShares
        $totShares += $VMShares[$vm.Name]
    }
   
    # Work out each VM's proportional CPU share
    ForEach ($vm in $VMs) {
        $rDetail = $tDetail.NewRow()
       
        $rDetail.Res_Pool = $ResPool.Name
        $rDetail.VM = $vm.Name
        $rDetail.Res_CPU_Shares = $ResPool.NumCpuShares
        $rDetail.VM_CPU_Shares = $VMShares[$vm.Name]
        If ($ResPool.Name -eq "Resources") {
            $rDetail.Eff_VM_Shares = $rDetail.VM_CPU_Shares
        } else {
            $rDetail.Eff_VM_Shares = $ResPool.NumCpuShares * ($rDetail.VM_CPU_Shares / $totShares)
        }
        $tDetail.Rows.Add($rDetail)
    }
}
 
Log "Done! Writing results out..."
$tSummary | Export-Csv -path ESX-ResPoolInfo-Summary.csv
$tDetail | Export-Csv -path ESX-ResPoolInfo-Detail.csv
$tSummary
</source>
 
=== ESX NIC Info ===
Provides a list of all vmnic speeds for ESX's connected to vCentre
<source lang="powershell">
$ESXs = Get-VMHost
 
Foreach ($esx in $ESXs) {
    Write-Host $esx.Name $esx.State
    $pNICs = (Get-VMHost -Name "MyESX*" | Get-View).Config.Network.Pnic
 
    $result = @{}
    Foreach ($pNIC in $pNICs) {
        $result[$pNIC.Device] = $pNIC.LinkSpeed.SpeedMB
    }
    $result = $result.GetEnumerator() | Sort-Object -Property Name
    $result
    Write-Host
}
</source>
 
=== ESX Log Tail ===
'''''Note that the below only seems to work for ESX3.5, I gave up trying to get it work for both v3 and v4, its a lot easier to just enable [[ESX#ESXi_Tech_Support_Mode|ESXi Tech Support Mode]] and tail the log'''''
Pointless for ESX (you can just use tail from the Service Console on the [[ESX#Useful_paths_.2F_logfiles|appropriate log]]), but a godsend it you're using ESXi (and have got used to tailing ESX logs).
<source lang="powershell">
$PollInterval = 1000    # msec (default - can be overrided by user)
 
#Get ESX to poll
$ESXs = Get-VMHost | Sort-Object -Property Name
Write-Host "`nWhich ESX's log do you want to tail?"
$num = 0
foreach ($esx in $ESXs) {
    Write-Host "[$num]" $ESXs[$num].Name
    $num++
}
$num = 0
$num = Read-Host "? [$num] "
$ESX = Get-VMHost $ESXs[$num]
Write-Host " "
 
# Get Log keys to look at
$keys = Get-LogType -VMHost $ESX
Write-Host "`nWhich log do you want to tail?"
$num = 0
foreach ($key in $keys) {
    Write-Host "[$num]" $keys[$num].Key
    $num++
}
$num = 0
$num = Read-Host "? [$num] "
$logKey = $keys[$num].Key
 
# Set polling interval
$PollInterval = Read-Host "`nWhat polling interval do you want to use (msec)? [$PollInterval]"
 
Write-Host "`nStarting log tail (press Ctrl+C to escape)...`n"
 
# First pass of log
$ESXLog = Get-Log $LogKey -VMHost $ESX
 
#Display last $lines
$LineNo = $ESXLog.LastLineNum - $lines
While ($LineNo -le $ESXLog.LastLineNum) {
    Write-Host $ESXlog.Entries[$LineNo]
    $LineNo++
}
 
#Polling loop
While (1) {
    Start-Sleep -Milliseconds $PollInterval
    try {
        $ESXLog = Get-Log $logKey -VMHost $ESX -StartLineNum $LineNo
    } catch {
        if (Select-String -InputObject $_ -pattern "The 0 argument is less than the minimum allowed range of 1" -Quiet) {
            Write-Host "ESX log is rolling over..."
            $ESXLog = Get-Log $logKey -VMHost $ESX
        } else {
            Write-Host "UNEXPECTED ERROR: $_"
            Exit
        }
    }
    $ESXlog.Entries
    $LineNo = $ESXLog.LastLineNum
}
</source>
 
=== ESX Discovered Networks Hint ===
This function provides the discovered network hints for the network interface its passed.  Bear in mind that its just a hint, for an ESX to be aware of a particular vLAN it needs to see traffic.  If there's no traffic it will show nothing.
 
Adapted from the following article on the VMware site blog http://blogs.vmware.com/vipowershell/2010/02/how-to-find-out-what-vlans-your-esx-hosts-can-really-see.html
 
<source lang="powershell">
function Get-ObservedIPRange {
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true,HelpMessage="Physical NIC from Get-VMHostNetworkAdapter")]
[VMware.VimAutomation.Client20.Host.NIC.PhysicalNicImpl]
$Nic
)
 
process {
$hostView = Get-VMHost -Id $Nic.VMHostId | Get-View -Property ConfigManager
$ns = Get-View $hostView.ConfigManager.NetworkSystem
$hints = $ns.QueryNetworkHint($Nic.Name)
 
foreach ($hint in $hints) {
foreach ($subnet in $hint.subnet) {
$observed = New-Object -TypeName PSObject
$observed | Add-Member -MemberType NoteProperty -Name Device -Value $Nic.Name
$observed | Add-Member -MemberType NoteProperty -Name VlanId -Value $subnet.VlanId
$observed | Add-Member -MemberType NoteProperty -Name IPSubnet -Value $subnet.IPSubnet
$observed | Add-Member -MemberType NoteProperty -Name BitRatePerSec -Value $nic.BitRatePerSec
Write-Output $observed
}
}
}
}
 
# Example use:
 
 
$result = Get-VMHost MyESX* | Get-VMHostNetworkAdapter | Where {$_.Name -Match ".*vmnic*"} | Get-ObservedIPRange | Sort-Object -Property Device, VlanId
$result | Export-Csv -path ESX-vLANs-Observed.csv
 
</source>
 
=== ESX CDP Info ===
Adapted from posted by LucD on VMware forum http://communities.vmware.com/message/977487
<source lang="powershell">
Get-VMHost | Sort -Property Name | %{Get-View $_.ID} | %{$esxname = $_.Name; Get-View $_.ConfigManager.NetworkSystem} | %{
  foreach($physnic in $_.NetworkInfo.Pnic){
    $pnicInfo = $_.QueryNetworkHint($physnic.Device)
    foreach($hint in $pnicInfo){
      Write-Host $esxname $physnic.Device $hint.connectedSwitchPort.DevId $hint.connectedSwitchPort.PortId
    }
  }
}
</source>
 
=== ESX Datastore to LUN Mapping ===
Its bizarrely difficult to be able to map VMware presented datastore names to the underlying LUN's, despite the fact that its readily available via the VI Client.  The following was adapted from the work of ''Catman'' found in this forum thread - http://communities.vmware.com/thread/240466#240466.  As I expect to maybe want some of the other fields available during the working my notes from working through this are to be found [[Datastore to LUN Mapping (PowerCLI)|here]]
<source lang="powershell">
# Thieved and adapted from the good work by catman...
# http://communities.vmware.com/thread/240466#240466
 
$objESX = Get-VMHost "My_ESX*"
 
# Get .NET views for host and storage system
$objViewESX = Get-View -id $objESX.id
$objViewESXstorageSys = Get-View -id $objViewESX.ConfigManager.StorageSystem
 
# Get FC HBAs
$HBAs = $objViewESXstorageSys.StorageDeviceInfo.HostBusAdapter | Where-Object {$_.Key -like "*FibreChannelHba*"}
 
foreach ($hba in $HBAs) {
    # Enumerate LUNs
    $LUNcount = $objViewESXstorageSys.StorageDeviceInfo.MultiPathInfo.Lun.Length
   
    for ($LUNidx = 0; $LUNidx -lt $LUNcount; $LUNidx++ ) {
        $objScsiLUN = $objViewESXstorageSys.StorageDeviceInfo.MultiPathInfo.Lun[$LUNidx]
       
        # Enumerate paths on LUN
        $PathCount = $objScsiLUN.Path.Length
       
        for ($PathIdx = 0; $PathIdx -lt $PathCount; $PathIdx++) {
            $objSCSIpath = $objViewESXstorageSys.StorageDeviceInfo.MultiPathInfo.Lun[$LUNidx].Path[$PathIdx]
           
            # Only care about one path, active on current HBA
            if (($objSCSIpath.PathState -eq "active") -and ($objSCSIpath.Adapter -eq $hba.Key)) {
                # Now get the disk that we want
                $objSCSIdisk = $objViewESXstorageSys.StorageDeviceInfo.ScsiLun | Where-Object{ ($_.CanonicalName -eq $objScsiLUN.Id) -and ($_.DeviceType -eq "disk") }
               
                # Now get the datastore info for disk
                $MountCount = $objViewESXstorageSys.FileSystemVolumeInfo.MountInfo.Length
               
                for ($MountIdx = 0; $MountIdx -lt $MountCount; $MountIdx++ ) {
                    if ($objViewESXstorageSys.FileSystemVolumeInfo.MountInfo[$MountIdx].Volume.Type -eq "VMFS" ) {
                        $objVolume = $objViewESXstorageSys.FileSystemVolumeInfo.MountInfo[$MountIdx].Volume
                       
                        $ExtentCount = $objVolume.Extent.Length
                       
                        for ($ExtentIdx = 0; $ExtentIdx -lt $ExtentCount; $ExtentIdx++ ) {
                            $objExtent = $objVolume.Extent[$ExtentIdx]
                           
                            # Match extent name to disk name
                            if ($objExtent.DiskName -eq $objSCSIdisk.CanonicalName) {
                                Write-Host($objSCSIdisk.Vendor + " " + $objSCSIdisk.Model + " " + $objSCSIdisk.CanonicalName + "`t" + $objVolume.Name)
                            }
                        }
                    }
                }
            }
        }
    }
}
</source>
 
Gives an output a bit like this...
<pre>
HP      HSV200          vmhba1:0:20  VMFS-DS-08
HP      HSV200          vmhba1:0:7    VMFS-DS-01
HP      HSV200          vmhba1:0:22  VMFS-DS-10
HP      HSV200          vmhba1:0:8    VMFS-DS-02
HP      HSV200          vmhba1:0:10  VMFS-DS-03
HP      HSV200          vmhba1:0:18  VMFS-DS-07
HP      HSV200          vmhba1:0:21  VMFS-DS-09
HP      HSV200          vmhba1:0:12  VMFS-DS-05
HP      HSV200          vmhba1:0:11  VMFS-DS-04
HP      HSV200          vmhba1:0:3    VMFS-DS-Templates
HP      HSV200          vmhba1:0:2    VMFS-DS-ISOs
HP      HSV200          vmhba1:0:30  VMFS-DS-SCRATCH
HP      HSV200          vmhba1:0:13  VMFS-DS-06
</pre>
 
=== Ping All VM's On ESX ===
Useful sanity check prior to and after network level changes
<source lang="Powershell">
$esxToFind = "MyESX*"
 
$ESX = get-vmhost $esxToFind
if (!$ESX) {
    Write-Host "ERROR: No ESX found with name matching expression $esxToFind" -Background Red -ForegroundColor DarkRed
    Exit
}
 
# Get list of VM's on $ESX
$VMs = $ESX | get-vm | Where {$_.PowerState -eq "PoweredOn"} | Sort -property Name
$objPing = New-Object system.Net.NetworkInformation.Ping
 
Foreach ($VM in $VMs) {
    Write-Host $VM.Name.PadRight(20) -nonewline
   
    # Get guest's primary IP address
    $ip = (Get-VMGuest -VM $vm).IPAddress[0]
    if (!$ip) {
        Write-Host "NULL - Skipping test" -Background DarkYellow -ForegroundColor Yellow
        Continue
    }
    Write-Host $ip.PadRight(17) -nonewline
    if ($ip -eq '0.0.0.0') {
        Write-Host "Skipping" -Background DarkYellow -ForegroundColor Yellow
        Continue
    }
       
    [string]$res = $objPing.Send($ip).Status
    if ($res.CompareTo("Success")) {                    # Returns 1 if $res doesn't match "Success" !!
        Write-Host $res -BackgroundColor DarkRed -ForegroundColor Red
    } else {
        Write-Host $res -BackgroundColor DarkGreen -ForegroundColor Green
    }
}
</source>
 
[[Category:VMware]]
[[Category:PowerShell]]

Latest revision as of 15:36, 4 October 2016

Redirect to: