Virtually everything is poshable
PowerCLI: Daily Report V2
Firstly I would like to thank everyone who took the time to comment on my previous Daily Report script, I really appreciate the feedback and have never had so many comments !
Now onto V2…
This one will take a while longer to run than the last script but as its a scheduled task we are not really worried about that, we are hardly going to sit there and watch it running !
I think you will agree the results are worth the wait:
What’s new
- Bug Fixes
- Active VMs count
- Inactive VMs count
- DRS Migrations count and list
- Correct NTP Server check for each host
- VMs stored on local datastores
- NTP Service check for each host
- vmkernel warning messages for each host
- VM CPU ready over x%
Bug Fixes
I have fixed the bugs which were mentioned in my previous posts comments, thanks to all for helping me find these. I have also added a few other tweaks along the way to improve output etc.
Active VMs count
In the General Details section there will now be a count of the number of VMs which are powered on.
Inactive VMs count
In the General Details section there will now be a count of the number of VMs which are powered off.
DRS Migrations count and list
In the General Details section there will now be a count of the number of DRS migrations over the given timescale (configurable in the config section), these migrations will also be listed in the DRS Migrations section later in the report:
Correct NTP Server and service check for each host
In the config section of the script you must specify your correct ntp server name, the script will then check to make sure all your hosts are using this NTP server and that the NTP service is running, if they are not it will report on these as below:
VMs stored on local datastores
The script will check to see if you have any VMs which reside on local storage if they do it will report these. At the top of the script you can add exclusions for things like templates or machines you know are allowed to be on local storage.
vmkernel warning messages for each host
Each host’s vmkernel log file will be checked and if any warning messages are being displayed these will be included in the report:
VM CPU ready over x%
Any VMs with a CPU %RDY over the configurable amount will be displayed in the report as below:
I hope you enjoy these additions and find them as useful as I do.
Please leave your comments below !
| Print article | This entry was posted by Virtu-Al on August 18, 2009 at 11:28, and is filed under PowerCLI, powershell, vmware. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |







(3)
(13)
(0)
about 1 year ago
Thanks for the nice script. We run it daily as a scheduled task and send the report to all the VMware administrators via e-mail. So first thing in the morning is to check e-mail and read the report.
One thing I noticed is that in the report the sum of active and in-active VMs is more then the number of VMs:
Number of Hosts: 16
Number of VMs: 190
Number of Clusters: 3
Number of Datastores: 46
Active VMs: 134
In-active VMs: 103
A little investigation showed that GET-VM (used for number of VMs) retrieves only VMs and not templates, while Get-View -ViewType VirtualMachine (used for active and in-active VMs) retrieves templates also. Maybe something for a next release to split the in-active VMs and the templates. Like this:
Number of Hosts: 16
Number of VMs: 190
Number of Clusters: 3
Number of Datastores: 46
Active VMs: 134
In-active VMs: 56
Templates: 47
about 1 year ago
@Robert-NL
Thanks
Great Idea, didn’t notice that one
about 1 year ago
So my question is about the ntp server check. I have several ntp servers listed for each ESX host just in case one ntp server is unavailable. It seems the get-vmhostntpserver -vhmost ESXhostname returns an array of ntp servers so in the script for the variable $ntpserver what would you do?
about 1 year ago
@Robert-NL,
Change the following line (to get rid of the templates in the “Number of VMs” count
$FullVM = Get-View -ViewType VirtualMachine
to this
$FullVM = Get-View -ViewType VirtualMachine | Where {-not $_.Config.Template}
$VMTmpl = Get-Template
Also add this line below “In-active VMs:” line
$MyReport += Get-HTMLDetail “Templates:” (@($VMTmpl).Count)
This will get you what you are looking for.
about 1 year ago
@Virtu-Al,
I noticed that “No VM Tools” report doesn’t work for me.
I changed
$NoTools = $FullVM | Where { $_.Runtime.PowerState -eq “poweredOn” } | Select Name, @{N=”ToolsVersion”; E={$_.Config.tools.toolsVersion}} | Where {$_.guest.toolsstatus -eq “toolsNotInstalled” -or $_.guest.toolsstatus -eq “toolsNotRunning”} | Select Name
to
$NoTools = $FullVM | Where {$_.Runtime.Powerstate -eq “poweredOn”
-And ($_.Guest.toolsStatus -eq “toolsNotInstalled” -Or $_.Guest.ToolsStatus -eq
“toolsNotRunning”)} | Select Name, @{N=”Status”;E={$_.Guest.ToolsStatus}}
This will display both the name of the VM and the status of the tools.
about 1 year ago
First let me say V2 of this script is awesome! I love the direction of this thing. It would be really cool if this type of script could be incorporated as a plugin to virtual center or the VESI. Great job Alan!!!
I get the following error regarding the percready section. It errors out like this on every vm and then just doesnt report the section. Any help on this would be great.
At F:\PSScripts\VMwareDailyReport\VMwareDailyReport.ps1:615 char:53
+ $myObj.PercReady = [Math]::Round((($v | Get-Stat <<<< -Stat
Cpu.Ready.Summation -RealTime | Where {$_.Instance -eq $cpunum} | Measure-Objec
t -Property Value -Average).Average)/200,1)
about 1 year ago
When running this great script i get the following error:
Attempted to divide by zero.
At D:\Vmware_Scripts\Report\Report_check.ps1:283 char:74
+ $MyDetails.PercFreeSpace = [math]::Round(((100 * ($ds.FreeSpaceMB)) / <<<< ($ds.CapacityMB)),0)
Attempted to divide by zero.
At D:\Vmware_Scripts\Report\Report_check.ps1:283 char:74
+ $MyDetails.PercFreeSpace = [math]::Round(((100 * ($ds.FreeSpaceMB)) / <<<< ($ds.CapacityMB)),0)
about 1 year ago
@rg
I will add this in the next version.
about 1 year ago
@Mike
Thanks, cool stuff, thats one for the next version
about 1 year ago
@Marc
Thanks for your kind comments, Im talking to the VESI people at the moment about being able to schedule this in their product…watch this space !
Not sure why the get-stat cmdlet isnt working in your environment, have you tried using the cmdlet to report other stats ?
about 1 year ago
@mlt
Thats a know bug, it will be fixed in the next version but is nothing to worry about, it just means you have no vms on local disk which is a good thing !
about 1 year ago
@Virtu-Al
Great. VMWs on Local disks is not done.
about 1 year ago
Perhaps is it possible to add the following:
In our environment we make use of a NTP server to synchronize the time on all clients & Servers.
We don’t want that the option synchronize the time with the ESX server in the VMware tools is enabled.
We use a script to check if there is a VM configured to sync the time with ESX server. If theres an VM so configurered we disable this option.
The script is:
Get-VM | Get-View | ? { $_.Config.Tools.syncTimeWithHost -eq $true }.
about 12 months ago
@rg
I have the same issue. You can fix it in this way (not pretty but gets the job done:
For the $ntpserver variable, quote each server and seperate with commas.
$ntpserver = “ntpserver1″, “ntpserver2″
Then change the —- NTP Check —- line to read like so:
$NTPCheck = @(Get-VMHost | Select Name, @{N=”NTPServer”;E={$_ | Get-VMHostNtpServer}}, @{N=”ServiceRunning”;E={(Get-VmHostService -VMHost $_ | Where-Object {$_.key -eq “ntpd”}).Running}} | Where {$_.ServiceRunning -eq $false -or $_.NTPServer -or $_.NTPServer[0] -ne $ntpserver[0] -or $_.NTPserver[1] -ne $ntpserver[1]})
continue to add to -or and increment the numbers till all your ntpservers are accounted for.
about 12 months ago
Alan,
I have a question. We have one vCenter installation, and a bunch of Datacenters listed but i want to run one of these reports for each datacenter. How would i go about doing that. I tried running it against a specific ESX server, but it threw a bunch of errors.
Any help would be greatly appreciated.
thanks
app
about 12 months ago
One more question for you Alan. As you may remember from a couple of my other posts, one of our vcenter servers has to be connected to on a non-standard port. we use 8843, rather than the standard 443. When i try and put Servername:8843 in the connect to line, it throws an error saying it can’t parse the :.
thanks for these great scripts
app
about 11 months ago
Hi guys, i love this script and will be implementing it for our admins. I wanted to ask is there any way I could also add report on data stores and % space left. Some of our sites have had close calls with datastores filling up due to admins not keeping an eye on them. Any help would be appreciated as i am a Powershell novice.
Thank you!
about 11 months ago
@mlt
I will add a section for that. Thanks
about 11 months ago
@Aaron
Hmmm, its not written to run against a certain datacenter but could be modified to do so. you should also be able to add a port to the connect-viserver line just add -port 8843 on the end.
about 11 months ago
@Rinc
This was added in V1, did you check the V1 post for a list of features ?
about 11 months ago
Virtu-Al, sorry, for the newbie post. I’m having problems running the script. No matter how I run the command, I get the following error. I’ve attempeted to put in the script on line 35 the user id, and I’ve left it blank with the same result.
“Connect-VIServer : Could not connect using the requested protocol.
At D:\admin\scripted_reports\DailyReportV2.ps1:399 char:29
+ $VIServer = Connect-VIServer <<<< $VISRV
Connect-VIServer : Could not connect using the requested protocol.
At D:\admin\scripted_reports\DailyReportV2.ps1:410 char:30
+ $VIServer = Connect-VIServer <<<< $VISRV"
about 11 months ago
Can I just make a suggestion – I found it an excellent practice to always define the collection up front. For example, instead of ‘$FullVM = Get-View -ViewType VirtualMachine’ , I always use ‘$FullVM = @(Get-View -ViewType VirtualMachine)’
With the second method, the basetype will _always_ be an array. Otherwise, if it only contains a single item it generally won’t be a basetype array and functions like .count or | measure-object won’t work correctly.
The functionality for the datacentre is realatively easy – my scripts use some primal script front end forms to give the user a choice of which datacentre (either a single one or all). The collections objects are then populated by using the -location (or in some cases, -datacenter) parameter.
Cheers,
Simon P.
about 11 months ago
@Simon Price
I agree, must have missed that one, thanks very much. Would be interested in seeing some of your scripts, are they available anywhere ?
about 11 months ago
@Mike
Mike, the credentials at the top of the script are only for the WMI calls to the VC server to gain service and event log information. You should be able to run this from an account which has access to your Virtual infrastructure just by running the script with a parameter of the VIServer name. Let me know if you need further help.
about 11 months ago
Hi,
Thanks for this daily report. It’s work fine. Is it possible to add the triggered alarm in the report ?
Regards,
about 11 months ago
Fantastic work Alan, you should do using powershell with Vmware training courses! I’d sign up!
about 11 months ago
@Barry Coombs
Thanks Barry, if your at the next UK VMUG you may get a nice suprise for free then, of course there is the beer tab afterwards !
about 11 months ago
Beautifull scripting, extremely usefull.
However, when i run it i get the following error:
Get-WmiObject : Access is denied. (Exception from HRESULT: 0×80070005 (E_ACCESS
DENIED))
At D:\Scripts\dailyreport.ps1:203 char:28
+ $Services = get-wmiobject <<<< win32_service -ComputerName $VISRV |
Where {$_.DisplayName -like "VMware*" }
Get-WmiObject : Access is denied. (Exception from HRESULT: 0×80070005 (E_ACCESS
DENIED))
At D:\Scripts\dailyreport.ps1:633 char:28
+ $ErrLogs = Get-WmiObject <<<=’” + $ConvDate +
“‘”) | Where {$_.Message -like “*VMware*”} | Select @{N=”TimeGenerated”;E={$_.
ConvertToDateTime($_.TimeGenerated)}}, Message
Get-WmiObject : Access is denied. (Exception from HRESULT: 0×80070005 (E_ACCESS
DENIED))
At D:\Scripts\dailyreport.ps1:647 char:29
+ $WarnLogs = Get-WmiObject <<<=’” + $ConvDat
e + “‘”) | Where {$_.Message -like “*VMware*”} | Select @{N=”TimeGenerated”;E={
$_.ConvertToDateTime($_.TimeGenerated)}}, Message
Any advice on how to resolve this?
Thanks!
about 11 months ago
How long would you expect this script to take to run?
about 11 months ago
@Ricardo
It depends on how big your infrastructure is, it can take 2 mins but can also take over 1hr (my prod env). I am adding some output to the next version just so you know its still doing things !
about 10 months ago
ah i figured out you can’t run this script on the same server that virtualcenter is installed on… Never mind my previous posting.
about 10 months ago
btw, a feature request for the next version :
Datastore usage rapport
We currently use this script for it :
connect-VIServer vc.company.com
$datum = (get-date -uformat “%D”)
$emailFrom = “some@domain.com”
$emailTo = “team@company.com”
$subject = “LUN Usage rapport ” + $datum
$smtpServer = “smtp.server.com”
Get-datastore | Sort-Object FreeSpaceMB -Descending | foreach-object {
$capacitymb = $_.CapacityMB
$FreeSpaceMB = $_.FreeSpaceMB
$UsedSpace = $capacitymb – $freespacemb
$perc = $UsedSpace / $capacitymb * 100
$perc = “{0:N1}” -f $perc
if ($perc -gt 95) {$output += “Datastore ” + $_.Name + ” is for ” + $perc + “% filled“}
Else {$output += “Datastore ” + $_.Name + ” is for ” + $perc + “% filled”}
}
$body = New-Object System.Text.Stringbuilder
[void] $body.AppendLine(“”);
foreach ($line in $output){
[void] $body.AppendLine($line.ToString())
}
[void] $body.AppendLine(“”);
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$MailMessage = new-object Net.Mail.MailMessage($emailFrom, $emailTo, $subject, $body.ToString())
$MailMessage.IsBodyHtml = $true
$MailMessage.ReplyTo = “some@domain.com”
$smtp.Send($MailMessage)
i’ll try to push it in on this version, if i succeed i’ll send you the code.
cheers!!
about 10 months ago
@Marcel
I’m getting the same Get-WmiObject : Access is denied errors. Tried it with two different admin accounts. Are there additional dependencies to be able to access the event logs?
about 10 months ago
@Chad
@Marcel
There are basically two types of data this report looks at:
1. The Virtual Infrastructure data which it uses PowerCLI and the credentials of the current logged on user, unless you change the connect-viserver statement in the script.
2. The vCenter Windows data (event logs and services) for which it uses the current logged on user or at the top you can specify domain\username and the next time the script runs you will be asked to input the same domain\username and password which is then stored in an encrypted credentials file for further use by the script.
It looks like Number 2 is failing for you so you either need to run the script as a user who has access to your vCenter server or use the setting at the top of the script to specify a domain\username that has access.
Hope this clears things up a little.
about 10 months ago
@Marcel
It can be run on the VC server but you will need powershell and powercli installed, it can basically run anywhere you have powercli and powershell installed.
I am confused by your feature request, this already exists and was actually the first thing I put in there, unless I am missing something !
about 10 months ago
@Virtu-Al
That’s what has me stumped. The two accounts I tested with are full admins on the virtual center server.
I’ll keep looking.
Thanks
Chad
about 10 months ago
@Virtu-Al
No pressure, but any ideas when the next version will be released?
about 10 months ago
@Chad
Very strange, can you log into your VC over RDP using the same account and look at the services ?
about 10 months ago
@bitsorbytes
Very soon, I just need to find time to put the final touches on, im going to leave some stuff till V4 as I already have lots of new features to add, thanks to all who have sent them through !
about 10 months ago
I ran this script on VI 4.0 with ESX 3.5 hosts and was immediately disconnected from my VI client and received error:
Exception calling “ReadNextTasks” with “1″ argument(s): “Unable to read data from the transport connection: An existing
connection was forcibly closed by the remote host.”
At C:\Program Files\VMware\Infrastructure\VIToolkitForWindows\scripts\DailyReportV2.ps1:352 char:45
+ $collection = $collectionImpl.ReadNextTasks <<<< ($tasknumber)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
I had to reboot vcenter to regain network connectivity. I waited and tried it again after business hrs and it did the same thing… any idea what may have happened?
about 10 months ago
@Marshall
I have never seen that before, all this script does is pull the information from the API much like the client does, it looks like an issue when its pulling the tasks, im guessing the GUI is ok when you click on your datacenter and then tasks & events tab ?
about 10 months ago
First off THANK YOU THANK YOU THANK YOU for this wonderful report. I noticed in your other post that you were considering adding CPU and Memory utilization and maybe some other features are you still considering? I will take any update you have to this script as I know it will blow me away or can you help me with adding that info CPU, MEM, Network, DISK, avg utilization or something similar
about 10 months ago
@ZOMAN
Thanks for the nice comment, keep an eye on my blog over the next couple of days…Shhhh !
about 10 months ago
@Virtu-Al Yes, the GUI is working just fine. I would LOVE to use this report if it didn’t disconnect my network connectivity to vcenter
about 10 months ago
One thing you may want to advertise or publish somehow.
In my environment I needed to make this modification:
Original:
$msg = new-object Net.Mail.MailMessage($from,$to,$subject,$body)
$msg.IsBodyHTML = $true
$mailer.send($msg)
New:
$msg = new-object Net.Mail.MailMessage($from,$to,$subject,$body)
$msg.IsBodyHTML = $true
$mailer.Credentials = [system.Net.CredentialCache]::DefaultNetworkCredentials
$mailer.send($msg)
Because my smtp server required authentication.
I also get authentication errors:
Get-WmiObject : User credentials cannot be used for local connections
At E:\PowershellScripts\dailyReports\DailyReportV2.ps1:204 char:28
+ $Services = get-wmiobject <<<< win32_service -Credential $creds -Com
puterName $VISRV | Where {$_.DisplayName -like "VMware*" }
Get-WmiObject : User credentials cannot be used for local connections
At E:\PowershellScripts\dailyReports\DailyReportV2.ps1:634 char:28
+ $ErrLogs = Get-WmiObject <<<=’” + $ConvDate + “‘”) | Where {$_.Message -like “*VMware*”} | Select @{N=”Ti
meGenerated”;E={$_.ConvertToDateTime($_.TimeGenerated)}}, Message
Get-WmiObject : User credentials cannot be used for local connections
At E:\PowershellScripts\dailyReports\DailyReportV2.ps1:648 char:29
+ $WarnLogs = Get-WmiObject <<<=’” + $ConvDate + “‘”) | Where {$_.Message -like “*VMware*”} | Select @{N=
“TimeGenerated”;E={$_.ConvertToDateTime($_.TimeGenerated)}}, Message
when scanning the local host (this is regardless of the permissions of the “user”) or when scanning remote hosts (I have 30 virtual centers under my management, most with 2-5 hosts attached). I don’t worry too much about these errors because they aren’t the output I’m most interested in.
about 10 months ago
Actually, I lied.
It isn’t gathering everything from the local machine, it’s not getting the logs from the local virtual center server, but it is from the remote servers.
about 10 months ago
I think your Daily Report script is great! I do get the exception error below because a couple of SAN luns are very low on disk space:
Attempted to divide by zero.
At C:\Scripts\DailyReportV2.ps1:276 char:74
+ $MyDetails.PercFreeSpace = [math]::Round(((100 * ($ds.FreeSpaceMB)) / <<<< ($ds.CapacityMB)),0)
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
about 10 months ago
@Jonathan Jewett
Sorry, I missed Alan’s comment earlier in the tread acknowledging the bug.
about 10 months ago
@Mike
Thanks Mike for the code.
I just learned that PowerState can also be Suspended. So I added the next line of code after In-active VMs:
$MyReport += Get-HTMLDetail “Suspended VMs:” (@($FullVM | Where { $_.Runtime.PowerState -eq “Suspended” }).Count)
about 10 months ago
If there are no local storage VMs ($LocalOnly is empty) I get an error on the next line:
$LocalVMs = @($LocalOnly | Get-VM | Where { $_.Name -notmatch $LVMDoNotInclude } |Get-View | Select Name, @{N=”VMX”;E={$_.Summary.Config.VmPathName}})
So I changed the code to:
# —- Local Storage VMs —-
If ($LocalOnly) {
$LocalVMs = @($LocalOnly | Get-VM | Where { $_.Name -notmatch $LVMDoNotInclude } |Get-View | Select Name, @{N=”VMX”;E={$_.Summary.Config.VmPathName}})
If (($LocalVMs | Measure-Object).count -gt 0) {
$MyReport += Get-CustomHeader “1″ “VMs stored on local datastores”
$MyReport += Get-HTMLTable $LocalVMs
$MyReport += Get-CustomHeaderClose
}
}