I apologize in advance for all the code, and how long the post is. I will make the code in Blue, so it stands out in the post.
Well, I just don't want to spend all day on this, so I'm hoping to find some help...again.
I want to output a message that only shows if a certain percentage of free space is low on a datastore (I have it at 15 percent). On my old script, I didn't create any objects, and for the datastore part I did this:
Function My-Data {
Function PercentFree { ## Start Function
param($ds)
[Math]::Round(($ds.FreeSpaceMB / $ds.CapacityMB * 100),0)
} ## End Function
} #end Function My-Data
The above script is just a portion of the script, but would output the information below:
------------------------------------------------------------------------------------------------------
Please do not place any VMs on the following datastores today (05-15-2012), they are low on space:
Datastore-vdisk
13% free
Total amount free = 251GB
Total capacity = 1900GB
What I want is that same information, but now I want to dynamically add it to an existing object. The code below is the new script (just a portion)
Function My-Function {
$vDataStore = New-Object PSObject
$vDataStore | Add-Member -MemberType NoteProperty -Name "vCenter Datastores" -Value ($Alldatastore).count
$vDataStore | Add-Member -MemberType NoteProperty -Name "Total storage capacity of datastores" -Value ("$([Math]::Round((($Alldatastore | measure -Property CapacityGB -sum).sum) / 1024))" + "(TB)")
$vDataStore | Add-Member -MemberType NoteProperty -Name "Total amount of free space on datastores" -Value ("$([Math]::Round((($Alldatastore | measure -Property FreeSpaceGB -sum).sum) / 1024))" + "(TB)")
Write "Datastore information "`r" ",
$vDatastore | fl
} #end My-Function
What I think the solution is, is that after this:
if ($vDataStore.PercentageFree -lt 15 -and $vDataStore.Datastore -notmatch 'ISOs')
I basically copied a portion of the old script to the new script, I changed some of the names around, and tried this
Function My-Test {
Function PercentFree { ## Start Function
param($ds)
[Math]::Round(($ds.FreeSpaceMB / $ds.CapacityMB * 100),0)
} ## End Function
$Alldatastore = Get-Datacenter "Center" | Get-Datastore
$OBJvDataStore = New-Object PSObject
$OBJvDataStore | Add-Member -MemberType NoteProperty -Name "vCenter Datastores" -Value ($Alldatastore).count
$OBJvDataStore | Add-Member -MemberType NoteProperty -Name "Total storage capacity of datastores" -Value ("$([Math]::Round((($Alldatastore | measure -Property CapacityGB -sum).sum) / 1024))" + "(TB)")
$OBJvDataStore | Add-Member -MemberType NoteProperty -Name "Total amount of free space on datastores" -Value ("$([Math]::Round((($Alldatastore | measure -Property FreeSpaceGB -sum).sum) / 1024))" + "(TB)")
$runOnce = 0
Foreach ($datastore in $Alldatastore) {
if ($runOnce -eq 0) { Write ("`r" + "Please do not place any VMs on the following datastores today " + "(" + (Get-date -Format "MM-dd-yyyy") + ")" + "," + " they are low on space: (Never place VMs on the `"ISOs`" datastore)"); "`r"; $runOnce++ }
$vDataStore = "" | Select Datastore, UsedSpace, Capacity, PercentageFree
$vDataStore.Datastore = $datastore.Name
$vDatastore.UsedSpace = [Math]::Round($datastore.FreeSpaceGB)
$vDataStore.Capacity = [Math]::Round($datastore.CapacityGB)
$vDataStore.PercentageFree = PercentFree $datastore
#I tried various things here
if ($vDataStore.PercentageFree -lt 15 -and $vDataStore.Datastore -notmatch 'ISOs') {
$Hash = New-Object PSObject -Property @{
"Datastores with low space" = $vDataStore.Datastore("{0:N0}% free" -f $vDataStore.PercentageFree)
}
#I tried adding a member, but I could not get it to work
# Add-Member -InputObject $OBJvDataStore "Datastores with low space" -Value $vDataStore.Datastore ("{0:N0}% free" -f $vDataStore.PercentageFree),`
#("Total amount free = " + $vDataStore.UsedSpace + "GB"),
#("Total capacity = " + $vDataStore.Capacity + "GB") }
} # End Foreach
Write "Test",
$OBJvDataStore | fl
}
}
Thanks in advance, if I need to just upload or copy and paste the entire script, just let me know. I just didn't think it was needed, because I only have an issue with this one part.
Can you try something like this ?
$vDataStore = "" | Select Datastore, UsedSpace, Capacity, PercentageFree,"Datastores with low space"
...
if ($vDataStore.PercentageFree -lt 15 -and $vDataStore.Datastore -notmatch 'ISOs') { $vDatastore."Datastores with low space" = ("{0:N0}% free" -f $vDataStore.PercentageFree) }
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks, I'm trying to work out the logic on that. I bumped up the percentage free to 90%, because I know there aren't any datastores with less that 15% now, but I get weird results
Here is the output
Datastore : --vdisk #removed name
UsedSpace : 984
Capacity : 2000
PercentageFree : 49
Datastores with low space : 49% free
vCenter Datastores : 20
Total storage capacity of datastores : 40(TB)
Total amount of free space on datastores : 17(TB)
Not sure where you see the "weird".
That datastore is 50% used, so 49% free seems reasonable to me.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
More datastores should be showing, there are 20, almost all of them should be showing since I changed to to less than 90% of freespace. Maybe I'm in the wrong foreach?
I'm not sure how you fit this function in your script, but the function should place the $vDatastore object on the pipeline for each datastore.
You could change the last line to something like this
...
Write "Test",
$OBJvDataStore | fl
$vDataStore
} }
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks, I tried that, but it's not working. I have something wrong in the Foreach section, because even if I say I want to see datastores that are less than 100% it still shows 1 datastore. Since I know the old script works, I'm going to just dig into it a bit more and see where I made the error. I'll post the results. Thanks again
Can you attach the current version of your script ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Line 106-119 is where the problem is, I still have small things to add, like automatically connecting to vCenter, but I just have not put them in yet. The section that starts "$runOnce = 0" (line 106) was from another script I had, I just tried to paste it in, and then work it out, I probably should have just started that part over, but it was right at the end, so I guess I became somewhat lazy about trying to redo it. Overall, the script outputs just what I want.
Obviously the SMTP address and email addresses are removed. The only other omission is on line 25 for the name parameter of the Get-Datacenter cmdlet.
Any help is appreciated, and any critques are welcome (be gentle).
The problem with this loop is that you will overwrite the properties in $vDatastore for each through the ForEach loop.
You assign a couple of properties outside the loop, that is ok.
But then in the loop, you fill in values for a number of other properties. Unfortunately these are the same properties in the same object. So only the last pass through the loop will be reported.
An alternative would be something like this
$vAllDataStore = New-Object PSObject
$vAllDataStore | Add-Member -MemberType NoteProperty -Name "vCenter Datastores" -Value ($Alldatastore).count
$vAllDataStore | Add-Member -MemberType NoteProperty -Name "Total storage capacity of datastores" -Value ("$([Math]::Round((($Alldatastore | measure -Property CapacityGB -sum).sum) / 1024))" + "(TB)") $vAllDataStore | Add-Member -MemberType NoteProperty -Name "Total amount of free space on datastores" -Value ("$([Math]::Round((($Alldatastore | measure -Property FreeSpaceGB -sum).sum) / 1024))" + "(TB)") $runOnce = 0
$vDatastoreTab = @()
Foreach ($datastore in $Alldatastore) { if ($runOnce -eq 0) { Write-Host "`r" + "Please do not place any VMs on the following datastores today (" + (Get-date -Format "MM-dd-yyyy") + "), they are low on space: (Never place VMs on the `"ISOs`" datastore)" Write-Host "`r" $runOnce++ } $vDataStore = "" | Select Datastore, UsedSpace, Capacity, PercentageFree
$vDataStore.Datastore = $datastore.Name
$vDatastore.UsedSpace = [Math]::Round($datastore.FreeSpaceGB) $vDataStore.Capacity = [Math]::Round($datastore.CapacityGB) $vDataStore.PercentageFree = PercentFree $datastore $vDatastoreTab += $vDatastore
if ($vDataStore.PercentageFree -lt 90 -and $vDataStore.Datastore -notmatch 'ISOs') { write $vDataStore.Datastore ("{0:N0}% free" -f $vDataStore.PercentageFree),`
( "Total amount free = " + $vDataStore.UsedSpace + "GB"),("Total capacity = " + $vDataStore.Capacity + "GB")"`r" } } #Writing the results, and the email will display them Write "Datacenters, Clusters, and ESXi Hosts:",
$vDataCenter,
$Cluster,
$ESXiInfo,
$('*'*100),
"VM and template information: "`r" ",
$VM, $('-'*80),
"Top ten VMs with the most memory: "`r" ",
$TopMemVM,
"Average memory assigned to VMs in vCenter is: $("$AvgVMMem" + "(MB)")", $('*'*100),
"Snapshot Information: "`r"",
$SnapObj, $('-'*80),
"VMs with 3 or more snapshots: "`r"",
$Snapshotsover2,
$('*'*100),
"Datastore Information: (Never place VMs on the 'ISOs' datastore) "`r" ",
$vAllDataStore,
$vDataStoreTab | fl
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks for the reply again LucD,
I guess that I had not run the entire script in awhile, I was only testing out the section for datastores, since that's what was giving me the problem. For the section I was testing, I did have the object names different, but not in the actual "final" script.
I'm having a small issue, and I see what it is. I'm writing all my info, but the way it is for the datastores section, it's writing the datastores with the percentage free that I want, but it's getting written at the very begininng, and not with the datastores section.
I took 3 datastores, and ran the debugger so that I could see.
Please do not place any VMs on the following datastores today (11-19-2012), they are low on space: (Never place VMs on the "ISOs" datastore)
-disk01
10% free
Total amount free = 183GB
Total capacity = 1900GB
Test
vCenter Datastores : 3
Total storage capacity of datastores : 6(TB)
Total amount of free space on datastores : 2(TB)
Datastore : -disk01
UsedSpace : 183
Capacity : 1900
PercentageFree : 10
Datastore : -disk02
UsedSpace : 574
Capacity : 2047
PercentageFree : 28
Datastore : disk01
UsedSpace : 989
Capacity : 2000
PercentageFree : 49
I see what's happening, the IF statement does its job, but since I'm writing out everything in order, the IF statement does not have an order, so it just writes out the info first.
I tried to write out data, and then move the IF statement, but then all the alignment is off, so I just need to see how to save the data in the IF statement and write out under the datastore section. I'm playing around with it, I'm getting close...I think.
Now that I think about it, maybe I should just have the datastore warning first, since a lot of people may not scroll down and view the entire report.
That sounds like a good idea.
Noteworthy points (and warnings) should better appear in the beginning of a report.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks LucD for all of your help. My script is finished, and of course, I immediately see improvements that I want to make, but those will just need to be put on hold for now. There is such a stark difference between my first summary script and this one, it looks 10x better. Well, back to learning Powershell.