Script to return the name of VMs in defined groups that appear on the same VMHost - powershell

What I am trying to achieve
I am writing a script that will run every hour and will send an email if certain VMs have been found running on the same vHost. I don't really care where each VM runs as long as one of its other VMs are not on the same vHost. The groupings are currently 4 VMs but I want it to work with N VMs in a group.
Firstly I define my groups of VMs like so:
$group1 = #("VM01", "VM02", "VM03", "VM04")
$group2 = #("SERVERA", "SERVER2")
$group3 = #("WIN01", "WIN02", "WIN03")
$groups = #($group1, $group2, $group3)
I can then do a ForEach on $groups and walk through each group in turn retrieving the name of the VMHost the VM is on:
ForEach($group in $groups) {
$vmhosts = New-Object 'string[]' $group.Length
For($i=0; $i -le ($group.Length -1); $i++) {
$vmhosts[$i] = Get-VM -Name $group[$i] | Get-VMHost
}
}
This gives me the IP/hostname of the VMhost into the array $vmhosts with position matching the index of the VM in its group array.
This is where I am struggling to figure out a way to determine if any VMs are on the same VMHost and report that in my email with text like the following for each VM on the same VMHost within a group (but reports on all groups):
VM01 is on the same VMHostas VM02
VM01 is on the same VMHostas VM03
VM02 is on the same VMHostas VM03
WIN02 is on the same VMHost as WIN03
If no group of VMs are on the same VMHosts then it simply returns, "All VMs are separated correctly."
What I have tried so far
I tried to retrieve the unique VMHost from $vmhosts with:
$unique = $vmhosts | Select -Unique
But then I need to know when VMs it was on that VMHost returned. So I tried to locate it in the $vmhosts which worked with 3 VMs but when expanded to 4 it fails to return anything.
I'm pretty sure this could be done much better....

How about
$vmGrp1 = #("VM01", "VM02", "VM03", "VM04")
$vmGrp2 = #("SERVERA", "SERVER2")
$vmGrp3 = #("WIN01", "WIN02", "WIN03")
$vmGrps = #($vmGrp1, $vmGrp2, $vmGrp3)
$finds = #()
foreach ($vmGrp in $vmGrps)
{
$vms = get-vm $vmGrp
$HostGrps = $vms | Group-Object #{e={$_.vmhost.name}}
$finds += $HostGrps | % {if ($_.Count -gt 1) {$_.Name + " has " + ( $_.Group | Select -ExpandProperty Name) }} # this breaks in PS v2: + $_.Group.Name}}
}
if ($finds) {$finds} else {"All VMs are separated correctly."}

Related

Combine (add) value from 2 different hashtable together

I was tasked with created a script to pull DHCP stats from a couple of particular scopes. I was able to get the stats no problem, however the output returned 2 results from the same scope. The problem is, whoever created this scope, created 2 identical scopes on 2 different servers but set the unusable address flipped in order to create "round robin"
I.e.
Server 1 has scope 10.10.92.0/23 (255.255.254.0)
10.10.92.48 as start of addresses
10.10.93.249 as end of addresses
10.10.93.1 to 10.10.93.249 IP **EXCLUSION**
Server 2 has scope 10.10.92.0/23 (255.255.254.0)
10.10.92.48 as start of addresses
10.10.93.249 as end of addresses
10.10.92.48 to 10.10.92.255 IP **EXCLUSION**
So my output in the HTML file would show:
1st result
2nd result
I redid my code and I manage to separate the results into hashtables, but now I want to combine the results and then generate a new html file based on that. The below code works but all attempts to try and combine the results resulted in failure or syntax error. Looking for a little guidance here.
$hashtable1 = #{} #create hash table
$scopes1 = Get-DhcpServerv4Scope -ComputerName NAMEOFSERVER | Select-Object ScopeId, SubnetMask, StartRange, EndRange, LeaseDuration, State | Where-Object -FilterScript {$_.ScopeId -like "10.10*" } #get all scopes
foreach ($scope in $scopes1) { $stats1 = Get-DhcpServerv4ScopeStatistics -ComputerName covdhcp5 -ScopeId $scope.scopeid.IPAddressToString | select Free, InUse, Reserved, percentageInUse
$array1 = #()
foreach ($var1 in $stats1) { $array1 += $var1 }
$hashtable1.add($scope.scopeid.IPAddressToString, $array1)}
$hashtable2 = #{} #create hash table
$scopes2 = Get-DhcpServerv4Scope -ComputerName NAMEOFSERVER | Select-Object ScopeId, SubnetMask, StartRange, EndRange, LeaseDuration, State | Where-Object -FilterScript {$_.ScopeId -like "10.10*" } #get all scopes
foreach ($scope in $scopes2) { $stats2 = Get-DhcpServerv4ScopeStatistics -ComputerName covdhcp6 -ScopeId $scope.scopeid.IPAddressToString | select Free, InUse, Reserved, percentageInUse
$array2 = #()
foreach ($var2 in $stats2) { $array2 += $var2 }
$hashtable2.add($scope.scopeid.IPAddressToString, $array2)}

Merge two PSCustomObjects into one- PowerShell

I need help in PowerShell to combine two outputs or two PSCustomObjects into One.
For example,
$services = Get-Service | Select Name, Starttype,Status
$processes = Get-Process | Select ID
I need the output with the table headers
Name, Starttype, Status, ID
I have already tried creating CSV and joining them but the problem is Process ID starts when the entire output ends for the services. I need them to a parallel.
Second I have tried to create PSCustomObjects but no luck.
Please help me with the PowerShell code.
Actual code that I'm trying to achieve.
**$exclusionItems = #()
$OasHighItems = #()
foreach($item in $items){
$exclusionItems += [PSCustomObject]#{
EXCLUSION_BY_NAME_OR_LOCATION = $item.EXCLUSION_BY_NAME_OR_LOCATION
EXCLUSION_EXCLUDE_SUBFOLDERS = $item.EXCLUSION_EXCLUDE_SUBFOLDERS
EXCLUSION_ON_READ= $item.EXCLUSION_ON_READ
}
}
foreach($oas in $oashigh){
$oashighItems += [PSCustomObject]#{
OAS_PROCESSES_LIST = $oas
}
}
$Array = #()
$Array = $exclusionItems,$oashighItems
$Array | Update-FirstObjectProperties | Export-Excel $ExcelParams -TableName Table -Show**
I'm assuming you want to join the two objects by their names, i.e. match the Process-Name with the Service-Name. For this you can loop over all processes & services, keep only those where service-name equals process-name, and use a calculated property to merge the result into one object:
$services = Get-Service;
Get-Process | ForEach-Object {$p = $_; $services |
Where-Object{$p.ProcessName -eq $_.Name} |
Select-Object Name,StartType,Status,#{n='ID';e={$p.ID}}}
The output on my machine is:
Name StartType Status ID
---- --------- ------ --
CcmExec Automatic Running 14856
CmRcService Automatic Running 5748
FusionInventory-Agent Automatic Running 5996
IBMPMSVC Automatic Running 3540
IntelAudioService Automatic Running 6104
... and so on ...

Parsing multiple valus in multiple variables

I am trying to find a way to execute a command in powershell and put each line of the result in a different variable to use them later in my script. For example if i execute the below command:
C:\> Get-VMHost -Name hq-esxi-prod-01a.nsx.gss | Get-VM | select Name
I will get the below:
Name
----
HQ-LinServ-01a
HQ-Win2012-01a
HQ-Web-02a
I want to have a script that will add each line in a different variable in a script (excluding the first which is name).
how can i do that.
Thank you for your help.
You can use Set-Variable in a loop to put each value in a separate variable:
$i = 0
... | Get-Vm | Select-Objet -Expand Name | ForEach-Object {
Set-Variable -Name "vm$i" -Value $_
$i++
}
However, that usually isn't good advice. It's more common to put all names in one (array) variable:
$vmList = ...| Get-Vm | Select-Object -Expand Name
so you can access individual names via $vmList[<index>], or (if you need access by some kind of name) in a hashtable:
$i = 0
$vmList = #{}
... | Get-Vm | Select-Objet -Expand Name | ForEach-Object {
$vmList["vm$i"] = $_
$i++
}
Best practice would depend on the particular scenario you need this for, though.
Thank you for your reply,
I have tried you answer but it seems that i am using PowerCLI for VMware it does not include Select-Object -Expand (not sure i had an exception), However your answer have mad me reach to a suitable answer for this.
I have used the below and it worked fine using foreach and adding the values in an array and then reading them as below:
$p1vmname = Get-VMHost -Name hq-esxi-prod-01a.nsx.gss | Get-VM | select Name
$p1vmlist = #()
foreach ($p1line in $p1vmname)
{
$p1vmlist += $p1line
}
$p1 = 0
do {
$x = $p1+1
Write-Host -BackgroundColor:Black -ForegroundColor:Yellow "vm number $x is "$p1vmlist[$p1]"."
$p1++
}
until ($p1 -eq $p1vmc)
}
However when using this the names was not totally correct as they had some additional characters as below:
vm number 1 is #{Name=HQ-Web-01a}
vm number 2 is #{Name=HQ-LinServ-01a}
vm number 3 is #{Name=HQ-Win2012-01a}
so i used split and trim to get rid of these as below and worked fine.
$p1vmname = Get-VMHost -Name hq-esxi-prod-01a.nsx.gss | Get-VM | select Name
$p1vmlist = #()
foreach ($p1line in $p1vmname)
{
$p1vmlist += $p1line
}
$p1 = 0
do {
$x = $p1+1
$p1vmlist[$p1] = ($p1vmlist[$p1]) -split("=") | Select-Object -Last 1
$p1vmlist[$p1] = $p1vmlist[$p1].trimend("}")
Write-Host -BackgroundColor:Black -ForegroundColor:Yellow "vm number $x is "$p1vmlist[$p1]"."
$p1++
}
until ($p1 -eq $p1vmc)
}
Output:
vm number 1 is HQ-Web-01a .
vm number 2 is HQ-LinServ-01a .
vm number 3 is HQ-Win2012-01a .
Thank you so much for your answer that helped me a lot.
I am really enjoying scripting now.

Get current IP addresses associated with an Azure ARM VM's set of NICs via Powershell

I'm trying to write some Powershell to get a list of Azure ARM vms (Not classic) and the currently associated IP addresses for their NICs.
In classic, this was part of the VM object, but in ARM it's a seperate object, and I'm struggling to get the Powershell to work in the way I want.
I've got the following code segment:
$nic = (((Get-AzureRmVM).NetworkProfile).NetworkInterfaces).Id
ForEach ($i in $nic) {
$nicname = $i.substring($i.LastIndexOf("/")+1)
Get-AzureRmNetworkInterface -Name $nicname -ResourceGroupName RGTEST | Get-AzureRmNetworkInterfaceIpConfig | select-object PrivateIpAddress,PrivateIpAllocationMethod
}
Which works, but only for VMs in the specified resource group 'RGTEST'.
It seems that Get-AzureRmNetworkInterface can only work when passed in the NIC Name and the ResourceGroupName, but I can't seem to get the RGname from the VM to be passed in.
Probably really easy, but I'm struggling with it!
I use this code to get all my ARM VMs, their private IP address and allocation method, it works across resource groups.
$vms = get-azurermvm
$nics = get-azurermnetworkinterface | where VirtualMachine -NE $null #skip Nics with no VM
foreach($nic in $nics)
{
$vm = $vms | where-object -Property Id -EQ $nic.VirtualMachine.id
$prv = $nic.IpConfigurations | select-object -ExpandProperty PrivateIpAddress
$alloc = $nic.IpConfigurations | select-object -ExpandProperty PrivateIpAllocationMethod
Write-Output "$($vm.Name) : $prv , $alloc"
}
Sample Output:
proddc : 10.0.0.4 , Static
stagedc : 10.1.0.4 , Static
Below is the script I used to get the Private and Public IP for an Azure ARM VM. If a VM has more than one NIC or IpConfig it would probably need to use a loop.
$rg = Get-AzureRmResourceGroup -Name "MyResourceGroup01"
$vm = Get-AzureRmVM -ResourceGroupName $rg.ResourceGroupName -Name "MyVM01"
$nic = Get-AzureRmNetworkInterface -ResourceGroupName $rg.ResourceGroupName -Name $(Split-Path -Leaf $VM.NetworkProfile.NetworkInterfaces[0].Id)
$nic | Get-AzureRmNetworkInterfaceIpConfig | Select-Object Name,PrivateIpAddress,#{'label'='PublicIpAddress';Expression={Set-Variable -name pip -scope Global -value $(Split-Path -leaf $_.PublicIpAddress.Id);$pip}}
(Get-AzureRmPublicIpAddress -ResourceGroupName $rg.ResourceGroupName -Name $pip).IpAddress
#Output:
Name PrivateIpAddress PublicIpAddress
---- ---------------- ---------------
ipconfig1 10.0.0.10 MyVM01-pip
40.80.217.1
For those that are looking for a solution that works across multiple subscriptions in a tenant, here's a script that loops through each subscription and reports on each private IP, NIC, VM, Resource Group and associated subscription. The output is in object format and is exported to a CSV file.
<#
.SYNOPSIS
Returns IP addresses and associated network interfaces and virtual machines across all Azure subscriptions the
user has access to.
.DESCRIPTION
This script returns all private IP addresses, the IP configuration resources they are associated with, the network interfaces and virtual
machines across all subscriptions. This script requires:
1. The Azure module to be installed (https://learn.microsoft.com/en-us/powershell/azure/install-az-ps?view=azps-2.8.0)
2. The user to be logged in to an Azure account using Connect-AzAccount / Connect-AzureRmAccount
3. The user must have subscription wide read permissions assigned for each subscription being queried
.PARAMETER FileName
Optional. Specify the file name and path for a CSV export.
.EXAMPLE
Get-IpAddressAllocation.ps1 -FileName .\AzureIpAddressReport.csv
#>
<#
.AUTHOR
Michael Wheatfill
.LICENSEURI
https://github.com/mwheatfill/mwheatfill.github.io/blob/master/LICENSE.txt
#>
#region Parameters
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]
$FileName
)
#endregion Parameters
#region Initializations
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
#endregion Initializations
#region Functions
function Get-IpAddresses {
param ()
$networkInterfaces = Get-AzNetworkInterface | Where-Object {$_.VirtualMachine -ne $null}
$virtualMachines = Get-AzVM
$results = #()
foreach($interface in $networkInterfaces) {
$ipConfigurations = $interface.IpConfigurations
foreach($ipConfig in $ipConfigurations) {
$vm = $virtualMachines | Where-Object {$_.Id -eq $interface.VirtualMachine.Id}
$ipDetails = [pscustomobject]#{
PrivateIpAddress = $ipConfig.PrivateIpAddress
VMName = $vm.Name
NetworkInterface = $interface.Name
IpConfigName = $ipConfig.Name
Primary = $ipConfig.Primary
ResourceGroup = $vm.ResourceGroupName
Subscription = $subscription.Name
}
$results += $ipDetails
}
}
return $results
}
#endregion Functions
#region Main
$subscriptions = Get-AzSubscription | Select-Object
$ipAddressesInAllSubscriptions = #()
$progressCount = 0
foreach ($subscription in $subscriptions) {
$progressCount++
$progressComplete = ($progressCount / $subscriptions.count * 100)
$progressMessage = "Gathering IP address informtion for subscription $progressCount of $($subscriptions.Count)"
Write-Progress -Activity $progressMessage -Status ($subscription.Name) -PercentComplete $progressComplete
$subscription | Select-AzSubscription > $null
$ipAddressesInSubscription = Get-IpAddresses -SubscriptionObject $subscription
$ipAddressesInAllSubscriptions += $ipAddressesInSubscription
}
$ipAddressesInAllSubscriptions | Sort-Object -Property Subscription, VMName, NetworkInterface, IpConfigName, Primary | Format-Table
$ipAddressesInAllSubscriptions | Export-Csv -Path $FileName -NoTypeInformation
#endregion Main
Since this question was asked back in 2016, Microsoft decided to no longer maintain the AzureRM module past Dec 2020, and along with it, the *-AzureRM* cmdlets. The Az module replaces it going forward.
However, there's a fast alternative for retrieving the list of Azure VMs with their associated IPs (private and public ones), by using Azure Resource Graph (ARG).
Concretely, for several thousand VMs, spread across several hundred Azure subscriptions, it takes mere seconds with ARG as opposed to 20+ minutes using Az's Get-AzVM cmdlet.
The script further down will report correctly even on multiple vmNics and multiple IP configurations per vmNic. It will retrieve all ARM VM data across the Azure subscriptions in the tenant. If running from either a local Powershell session or Cloud Shell, make sure you have the Az.ResourceGraph module installed first.
Sample output on a small test Azure tenant:
The script follows:
function RunARGquery {
param (
[string[]]$SubscriptionIds,
[string]$ARG_query
)
$fullResultSet = #()
$pageSize = 5000
# Subscription batching code below taken
# from https://learn.microsoft.com/en-us/azure/governance/resource-graph/troubleshoot/general#toomanysubscription
# Create a counter, set the batch size, and prepare a variable for the results
$counter = [PSCustomObject] #{ Value = 0 }
$batchSize = 1000
# Group the subscriptions into batches
$subscriptionsBatch = $subscriptionIds | Group -Property { [math]::Floor($counter.Value++ / $batchSize) }
$currentBatchNo = 0
# Run the query for each batch
foreach ($batch in $subscriptionsBatch) {
$pagesProcessedSoFar = 0
do {
$results = #()
if($pagesProcessedSoFar -eq 0) {
$results = Search-AzGraph -Subscription $batch.Group -Query $ARG_query -First $pageSize
}
else {
$results = Search-AzGraph -Subscription $batch.Group -Query $ARG_query -First $pageSize -Skip ($pagesProcessedSoFar * $pageSize)
}
$pagesProcessedSoFar++
Write-Host "Processed $pagesProcessedSoFar pages so far. A number of $(($results | Measure-Object).count) results returned in the last page"
$fullResultSet += $results
} while(($results | Measure-Object).count -eq $pageSize)
Write-Host "Finished subscription batch $currentBatchNo"
$currentBatchNo++
}
return $fullResultSet
}
# Get the date/time now, for timestamping both output files
$currentDateTime = Get-Date -Uformat "%Y%m%d-%H%M%S"
Write-Host "Getting list of Azure subscriptions..."
# Fetch the full array of subscription IDs
$subscriptions = Get-AzSubscription
$subscriptionIds = $subscriptions.Id
Write-Host "Found $(($subscriptionIds | Measure-Object).count) subscriptions"
# ARG query from Listing 23
$ARM_ARG_query = #"
Resources
| where type =~ 'microsoft.compute/virtualmachines'
| project id, vmId = tolower(tostring(id)), vmName = name
| join (Resources
| where type =~ 'microsoft.network/networkinterfaces'
| mv-expand ipconfig=properties.ipConfigurations
| project vmId = tolower(tostring(properties.virtualMachine.id)), privateIp = ipconfig.properties.privateIPAddress, publicIpId = tostring(ipconfig.properties.publicIPAddress.id)
| join kind=leftouter (Resources
| where type =~ 'microsoft.network/publicipaddresses'
| project publicIpId = id, publicIp = properties.ipAddress
) on publicIpId
| project-away publicIpId, publicIpId1
| summarize privateIps = make_list(privateIp), publicIps = make_list(publicIp) by vmId
) on vmId
| project-away vmId, vmId1
| sort by vmName asc
"#
Write-Host "Running ARM ARG query..."
RunARGquery -SubscriptionIds $subscriptionIds -ARG_query $ARM_ARG_query `
| Select-Object -ExcludeProperty ResourceId `
| Sort-Object -Property vmName `
| Export-Csv -NoTypeInformation "AzureVMs_$currentDateTime.csv"
If you're looking to also retrieve the classic Azure VMs (ASM model), using ARG as well, a script is available here. A detailed discussion around the Azure Resource Graph queries for retrieving the VM data, throttling, permissions, etc can be found in this post.
Here's a script that I use to get relevant VM Private/Public IP Address info used for various tasks. It will run from MAC OS or Windows OS as I've a MAC with a Widows 10 Parallels VM running for compatibility. Use it as you wish.
It will export to CSV and attempt to open in Excel or whatever is registered to the CSV extension. In the example below it was saved as PS_AzureRM_Get_VMs.ps1 or just run it as raw code in PowerShell.
#Login to AZURE from PowerShell
#Below works in MAC/Linux PowerShell 6.0.1+ and Windows WMF 4.0+
#pwsh on MAC OS or powershell_ise.exe on Windows
#Connect-AzureRmAccount (Login-AzureRMAcount and Add-AzureRMAccount are the older Azure cmdlets)
# Goto URL https://microsoft.com/devicelogin and the password it provides example Q9KZ3HGN2
# You may need to select-azurermsubscription -subscriptionid $SubscriptionID #Define $SubscriptionID = 'replace everything with your actual subscription xxx-xxxx-xxx'
#Example location using the . way of running a script or just cut and paste to PowerShell
#Example location using the . way of running a script
#MAC PWSH syntax
#. ~/Documents/Scripts/AzureRM/PS_AzureRM_Get_VMs.ps1
#Windows PowerShell.exe/PowerShell_ISE.exe syntax
#. $env:userprofile\Scripts\AzureRM\PS_AzureRM_Get_VMs.ps1
$Project="DevOps"
$clientFilePrefix="AzureRM"
$clientFileCampaign="VMs"
#Get Date Time
$Date = ([DateTime]::Now).ToString("yyyyMMdd")
$Time = ([DateTime]::Now).ToString("HHmmss")
$DateStart=get-date
#Change to Windows Path if running in Windows $env:USERPROFILE
If ($($env:USERPROFILE)) {
$fldrRoot="$($env:USERPROFILE)\"
$fldrPathseparator='\'
} Else {
$fldrRoot="~/"
$fldrPathseparator='/'
}
# Make Directory if not exist
$fldrPath=$fldrRoot+"Documents"+$fldrPathseparator+$Project+$fldrPathseparator+$clientFilePrefix+$fldrPathseparator+$clientFileCampaign
New-Item -ErrorAction Ignore -ItemType directory -Path $fldrPath
#Make Imports Folder
$fldrPathimports=$fldrPath+$fldrPathseparator+"Imports"
New-Item -ErrorAction Ignore -ItemType directory -Path $fldrPathimports
#Make Exports Folder Directory
$fldrPathexports=$fldrPath+$fldrPathseparator+"Exports"
New-Item -ErrorAction Ignore -ItemType directory -Path $fldrPathexports
#Assign the variable to the export file Prefix
$VMInfo_Export=$fldrPathexports+$fldrPathseparator+$clientFilePrefix+"_"+$Project+"_"+$clientFileCampaign+"_"+$Date+"_"+$Time+".csv"
#Create a Table to use for filtering the results
$VMInfo = New-Object System.Data.DataTable
#Now Add some columns for use later
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'ResourceGroup',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'VM',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Location',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'VM_ID',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'VM_NIC',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'IP',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Public_IP_Name',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Public_IP',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'IP_MAC',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Priv_Dyn',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Status',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Date_Time',([String])))
$VMInfo_Array_Count=($VMInfo | Measure-Object | Select Count).Count
#List the Array to show it='s empty
Write-Host "Created Array VMInfo with $VMInfo_Array_Count objects"
$Date_Time=([DateTime]::Now).ToString("yyyy/MM/dd")+" "+([DateTime]::Now).ToString("HH:mm:ss")
#Check the OS type
If ($($ENV:OS)) {$OSTYPE="WINDOWS";Write-Host "The OS is"$OSTYPE" Based"} Else {$OSTYPE="LINUX";Write-Host "The OS is"$OSTYPE" Based"}
#Get the VM's
$VMs = Get-AzureRmVM
$VMstatus = Get-AzureRmVM -Status
#Get the NIC and their properties for matching against the VMs
$NICs = get-azurermnetworkinterface | where VirtualMachine -NE $null #skip NICs with no VM
#Get the Public IPs for matching against the VMs
#Public IPs work only if the naming convention starts with the VM Name used in Azure
$PublicIPs=Get-AzureRmPublicIpAddress | Select-Object Name,ResourceGroupName,IpAddress
#Now Loop through the NICs in Azure and match against the VMs and the Public IPs
ForEach ($nic in $NICs)
{
#Get the VM Info
$VM = $VMs | where-object -Property Id -EQ $nic.VirtualMachine.id
$VM_Name = $($VM.name)
$VM_Location = $($VM.Location)
$VM_Resourcegroup = $($VM.ResourceGroupName)
$VM_ID = $($VM.VMid)
$VM_NIC = $nic.Name -Join ';'
$VM_Status = (($VMstatus | Where {$_.ResourceGroupName -eq $VM_Resourcegroup -and $_.Name -eq $VM_Name}).PowerState).Replace('VM ', '')
$VM_IP = ($nic.IpConfigurations | select-object -ExpandProperty PrivateIpAddress) -Join ';'
$VMPIPName = ($nic.IpConfigurations.PublicIpAddress.Id -Split '/')[-1]
$VM_PublicIP = ($PublicIPs | Where-Object {$_.ResourcegroupName -eq $VM_Resourcegroup -and $_.Name -like "$VMPIPName"} | Select IpAddress).IpAddress
$VM_IP_MAC = (($nic | Select MacAddress).MacAddress) -Join ';'
$VM_Alloc = $nic.IpConfigurations | select-object -ExpandProperty PrivateIpAllocationMethod
#Uncomment this to check the values before going into the Array $VMINFO
#Write-Output "$($VM.ResourceGroupName), $($VM.Name), $($VM.VMid), $($VM.Location), $VM_IP, $VM_PublicIP, $VM_IP_MAC, $VM_Alloc"
#Now populate the $VMInfo array
$row = $VMInfo.NewRow()
$row.'ResourceGroup'=$VM_Resourcegroup
$row.'VM'=$VM_Name
$row.'VM_ID'=$VM_ID
$row.'VM_NIC'=$VM_NIC
$row.'Location'=$VM_Location
$row.'IP'=$VM_IP
$row.'Public_IP_Name'=$VMPIPName
$row.'Public_IP'=$VM_PublicIP
$row.'IP_MAC'=$VM_IP_MAC
$row.'Priv_Dyn'=$VM_Alloc
$row.'Status'=$VM_Status
$row.'Date_Time'=$Date_Time
$VMInfo.Rows.Add($row)
}
cls
$TotalTime=(NEW-TIMESPAN –Start $DateStart –End $(GET-DATE))
Write-Host "Script Ran in $($TotalTime.Hours) hours and $($TotalTime.Minutes) minutes and $($TotalTime.Seconds) seconds"
#Export the Info
Write-Host "Exporting VMINFO Report to `n`t$($VMInfo_Export)"
$VMInfo | Export-CSV -NoTypeInformation -Path $VMInfo_Export
#Depending on OS run the Open/Start command for the CSV Export
If ($OSTYPE -eq "LINUX") {open $VMInfo_Export} `
ElseIf ($OSTYPE -eq "WINDOWS") {start $VMInfo_Export} `
Else {Write-Host "Unknown OS"}
break
##### ###### #####
####### ###### #####
## Extra Tasks to Filter the Exports
##### ###### #####
####### ###### #####
#Get the Array Size
$VMInfo_Array_Count=($VMInfo | Measure-Object | Select Count).Count
#ECHO the Array size
Write-Host "`n`n***** *****"
Write-Host "Array VMInfo has $VMInfo_Array_Count objects"
Write-Host "***** *****"
break
#Shows Configured Resource Group Names
$VMInfo_ResourceGroupNames=($vminfo | Select ResourceGroup -Unique).ResourceGroup
#ECHO Configured Resource Group Names
Write-Host "`n`n***** *****"
Write-Host "***** List of Groups*****"
Write-Host "***** *****"
$($VMInfo_ResourceGroupNames)
break
#Get DC's from resource Group Name
$VM_Environment="dtdaily"
$VMInfo_GetDCs=$vminfo | where {$_.ResourceGroup -eq $VM_Environment -and $_.VM -like "*dc*"}
#ECHO DC's from resource Group Name
Write-Host "`n`n***** *****"
Write-Host "***** List of DC's"
Write-Host "***** *****"
$($VMInfo_GetDCs)
break
#Get Public IP VMs
$VMInfo_PublicIPs=$vminfo | Where {$_.Public_IP -like "*.*"}
#ECHO Public IP VMs
Write-Host "`n`n***** *****"
Write-Host "***** *****"
Write-Host "***** List of Public IP VMs"
Write-Host "***** *****"
$($VMInfo_PublicIPs)
break
#ECHO All VMs
$VMInfo
Break
I have searched a lot and finally succeeded. Using resource group name and azure vm name, you can retrieve private or public ip address:
$Resourcegroup=""
$VmName=""
$VmNetworkdetails= (((Get-AzureRmVM -ResourceGroupName $Resourcegroup -Name $VmName).NetworkProfile).NetworkInterfaces).Id
$nicname = $VmNetworkdetails.substring($VmNetworkdetails.LastIndexOf("/")+1)
$privateIp =(Get-AzureRmNetworkInterface -Name $nicname -ResourceGroupName $Resourcegroup)|Select-Object -ExpandProperty IPConfigurations
write-host $privateIp.PrivateIpAddress

How to get server information from VMware

I have access to the VMWare GUI and I can easily export all the columns such as UPtime, IPAddress, Notes, DNS, GuestOs, State, Name and so on.
I want to right a script that can automatically get this information daily. So gar I was only able to get the server name, power state and VMhost. for some reason VMware is making it so hard to extract that information. I used the script below and I thought by adding the columns I mentioned above to this script, I should be able to retireve the data I need. But it doesn't work that way. Can someone please tell me how I can get this information?
Thanks,
Add-PSSnapin vmware.vimautomation.core
Connect-VIServer SERVERNAME
Get-VM|Select Name, VMHost, Id, PowerState
Exit 0
After digging into the system and many hours of research I found the solution. I just wish VMWare would make it easier to retrieve data or at least improve the manual.
The following code creates two files; one with the server information and another one with Uptime information.
Get-VM | select name,VMHost, #{ Name = "IP Addresses"; Expression = { $_.Guest.IPAddress }}, #{ Name = "PowerState"; Expression = { $_.Guest.State }} , #{ Name = "GuestOS"; Expression = { $_.Guest }}, Notes | Export-Csv -Path "HQstat.csv"
Get-Stat -Entity * -Stat sys.uptime.latest -Realtime -MaxSamples 1| Export-Csv -Path "HQtime.csv"
Why not use the views? They have all the information that you need. Code below assumes you are connected to the vCenter.
$vmView = Get-View -ViewType VirtualMachine -Property Name,Config,Guest,Runtime
$hostView = Get-View -ViewType HostSystem -Property Name
$date = Get-Date
Foreach ($vm in $vmView)
{
If ($vm.Runtime.BootTime -ne $null)
{
$dateDiff = $date.Subtract($vmView.Runtime.BootTime)
}
Else
{
$dateDiff = $null
}
foreach ($h in $hostView)
{
If ($vm.Runtime.Host -eq $h.MoRef)
{
$tempHost = $($h.Name)
Break
}
}
$global:Export += #([PSCustomObject]#{
VMName = $($vm.Name)
ID = $($vm.Config.Uuid) #or use $($vm.MoRef)
Host = $tempHost
PowerState = $($vm.Guest.GuestState)
IPAddress = $($vm.Guest.IPAddress)
Notes = $($vm.Config.Annotations)
UptimeMinutes = $($dateDiff.TotalMinutes)
})
$dateDiff = $null
$tempHost = $null
}
$exportFileName = "C:\temp\VMInformation.csv"
$Export | Export-Csv $exportFileName -Force -NoTypeInformation