I have a script that I run against a vCenter server. Basically finds all vm's in vCenter and ruins a get-wmiobject command against them to get the VMNAME, Partition, Offset and Status and exports it to excel.
Here's a sample output of the data that gets exported to excel:
VMName | Partition | Offset | Status |
pdxvvmdb1 | Disk #0, Partition #1 | 8193150KB | Partition NOT aligned |
pdxvvmdb1 | Disk #0, Partition #1 | 8193150KB | Partition NOT aligned |
My "problem" is its not giving me the correct partition info in excel (via system info), see below.
It only has 1 vmdk with 2 partitions, so it should output both partition 1 and 2 and the offsets, since they're both incorrect?
Also looking to add a line to the script to add the datastore and the vmdk file location ([PDXESX1_RAID] pdxvvmdb1/pdxvvmdb1.vmdk) in this case and have that output to the excel. Possible?
I attached the script since its pretty long....
I made the same mistake you did in the beginning, the $Details object has to be created at the lowest level.
Like this
# Add-PSSnapin vmware.vimautomation.core connect-viserver vspheredev $myCol = @() $mycol.Initialize() $vms = get-vm | where {$_.PowerState -eq "PoweredOn" -and $_.Guest.OSFullName -match "Microsoft Windows*" } | Sort Name foreach($vm in $vms) { Try { $wmi = get-wmiobject -class "Win32_DiskPartition" -namespace "root\CIMV2" -ComputerName $vm -ErrorAction silentlycontinue foreach ($objItem in $wmi) { if ($objItem.StartingOffset % 64kb -eq 0){ $Details = "" | Select-Object VMName, Partition, Offset, Status, VMDKPath
$Details.VMName = $vm.name
$details.VMDKPath = $vm.HardDisks[0].Filename
$Details.Partition = $objItem.Name
$details.offset = "$([long]$($objitem.StartingOffset)/1KB)KB"
$Details.Status = "Partition aligned" } else { $Details = "" | Select-Object VMName, Partition, Offset, Status, VMDKPath
$Details.VMName = $vm.name
$details.VMDKPath = $vm.HardDisks[0].Filename
$Details.Partition = $objItem.Name
$details.offset = "$([long]$($objitem.StartingOffset)/1KB)KB"
$Details.Status = "Partition NOT aligned" } $myCol += $Details } } catch { $Details = "" | Select-Object VMName, Partition, Offset, Status, VMDKPath
$Details.VMName = $vm.name
$details.VMDKPath = ""
$Details.Partition = "error"
$details.offset = ""
$Details.Status = "error"
$myCol += $Details
} } $mycol | Export-Csv -NoTypeInformation "H:\Excel_Reports\NEW_Production_PartitionAlignment.csv"
#output errors to file $error >> "c:\temp\partition-check-errors.txt" $error.clear()
Note that in the VMDKPath property the script stores the path of the 1st VMDK.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Since you creating the $Details object outside the partition loop, you are always referring to the same object.
In you $myCol there will be only 1 object for each VM.
Since you are using only 1 VMDK, you can find the datastorepath to the VMDK quite easy.
Something like this
# Add-PSSnapin vmware.vimautomation.core connect-viserver vspheresea $myCol = @() $mycol.Initialize() $vms = get-vm | where {$_.PowerState -eq "PoweredOn" -and ` $_.Guest.OSFullName -match "Microsoft Windows*" } |
Sort Name foreach($vm in $vms) { Try { $wmi = get-wmiobject -class "Win32_DiskPartition" -namespace "root\CIMV2" -ComputerName $vm -ErrorAction silentlycontinue foreach ($objItem in $wmi) { $Details = "" | Select-Object VMName, Partition, Offset, Status, VMDKPath
$Details.VMName = $vm.name
$details.VMDKPath = $vm.HardDisks[0].Filename
if ($objItem.StartingOffset % 64kb -eq 0){ $Details.Partition = $objItem.Name
$details.offset = "$([long]$($objitem.StartingOffset)/1KB)KB"
$Details.Status = "Partition aligned" } else
{ $Details.Partition = $objItem.Name
$details.offset = "$([long]$($objitem.StartingOffset)/1KB)KB"
$Details.Status = "Partition NOT aligned" } $myCol += $Details
} } catch { $Details = "" | Select-Object VMName, Partition, Offset, Status, VMDKPath
$Details.VMName = $vm.name
$Details.Partition = "error"
$details.offset = ""
$Details.Status = "error"
$myCol += $Details
} } $mycol | Export-Csv -NoTypeInformation "H:\Excel_Reports\Production_PartitionAlignment.csv" #output errors to file $error >> "c:\temp\partition-check-errors.txt"
$error.clear()
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Brilliant.... what about the VM's that actually have multiple VMDK's though? Will it list out all, if any?
Ah, now that is a problem. There is, afaik, no fool-proof way to make a link between the VMDK and the partitions you create in the guest OS.
That's why I said that with 1 VMDK it is possible, but with more than 1 VMDK, it's a problem I'm afraid.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Good to know.
It still doesnt look like the script is getting the right data though. For instance, output data:
VMName | Partition | Offset | Status |
seavvafile2 | Disk #1, Partition #0 | 32KB | Partition NOT aligned |
seavvafile2 | Disk #1, Partition #0 | 32KB | Partition NOT aligned |
System Info data:
"Didnt paste in, see attached file."
This VM has 2 VMDK's (which I dont really care about) but Im assuming if it out put the right info in the spreadsheet (Disk #0, partition #0, and disk #1 partition #0) I could put 2 and 2 together and assume that there are 2 VMDK's since there are 2 Disks showing in the Partition column.
Didn't you get the VMDKPath property ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I just tested on a VM with 4 VMDK and 2 partitions on the first disk.
Looked ok to me
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I had to play around with the script you pasted... running it now to see what it comes up with.
Is yours outputting the proper VMDK path?
jsmith1 | Disk #1, Partition #0 | 31.5KB | Partition NOT aligned | [DS1] jsmith1/jsmith1.vmdk |
jsmith1 | Disk #1, Partition #0 | 31.5KB | Partition NOT aligned | [DS1] jsmith1/jsmith1.vmdk |
Mine is still showing the duplicate disk # and the VMDK location is the same.
The bottom VMDK should be [DS] jsmith1/jsmith1_1.vmdk and the tiop disk should be Disk #0 Partition #0.... while the bottom should be Disk #1, Partition #0
I attached the script to see if Im missing anything
I made the same mistake you did in the beginning, the $Details object has to be created at the lowest level.
Like this
# Add-PSSnapin vmware.vimautomation.core connect-viserver vspheredev $myCol = @() $mycol.Initialize() $vms = get-vm | where {$_.PowerState -eq "PoweredOn" -and $_.Guest.OSFullName -match "Microsoft Windows*" } | Sort Name foreach($vm in $vms) { Try { $wmi = get-wmiobject -class "Win32_DiskPartition" -namespace "root\CIMV2" -ComputerName $vm -ErrorAction silentlycontinue foreach ($objItem in $wmi) { if ($objItem.StartingOffset % 64kb -eq 0){ $Details = "" | Select-Object VMName, Partition, Offset, Status, VMDKPath
$Details.VMName = $vm.name
$details.VMDKPath = $vm.HardDisks[0].Filename
$Details.Partition = $objItem.Name
$details.offset = "$([long]$($objitem.StartingOffset)/1KB)KB"
$Details.Status = "Partition aligned" } else { $Details = "" | Select-Object VMName, Partition, Offset, Status, VMDKPath
$Details.VMName = $vm.name
$details.VMDKPath = $vm.HardDisks[0].Filename
$Details.Partition = $objItem.Name
$details.offset = "$([long]$($objitem.StartingOffset)/1KB)KB"
$Details.Status = "Partition NOT aligned" } $myCol += $Details } } catch { $Details = "" | Select-Object VMName, Partition, Offset, Status, VMDKPath
$Details.VMName = $vm.name
$details.VMDKPath = ""
$Details.Partition = "error"
$details.offset = ""
$Details.Status = "error"
$myCol += $Details
} } $mycol | Export-Csv -NoTypeInformation "H:\Excel_Reports\NEW_Production_PartitionAlignment.csv"
#output errors to file $error >> "c:\temp\partition-check-errors.txt" $error.clear()
Note that in the VMDKPath property the script stores the path of the 1st VMDK.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I get a parsing error on line 5. Right after the -and. It looks like it needs a value?
$vms = get-vm | where {$_.PowerState -eq "PoweredOn" -and ` $_.Guest.OSFullName -match "Microsoft Windows*" } | Sort Name
That back-tick had to go, I updated the code above
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Its parsing out the info into excel properly now, but like you said, is only going to populate the one VMDK file path...
Im not sure I need this info, but it wont hurt to be in the script.
Thanks!
Im looking to add Disk and Partition into separate tabs at the top, so I can filter them based on one or the other.
Is there a way to separate the 2?
From the looks of it, theres only a Partition Item in System Information.....
The Split function would do that. Something like this
$Details.Disk,$Details.Partition = $objItem.Name.Split(',')
You will need to add the property Disk to the $Details object.
The $ObjItem.Name is split at the comma, the first part goes to $Details.Disk, the 2nd part goes to $Details.Partition.
Let me know if that works for you.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Im not that familiar with the split command, but I did add
$Details = "" | Select-Object VMName, Disk, Partition, Offset, Status, VMDKPath
to the 3 different areas of the script.
Do I need to add the line below to all the 3 $Details fields below that too? Or just one?
$Details.Disk,$Details.Partition = $objItem.Name.Split(',')
I've added all 3 to the "if, else, and catch" details section but Im thinking thats wrong....
EDIT:
I've done a find/replace in excel to get rid of ", Partition #0", ", Partition #1" etc... Seems to get rid of the data I dont need.
I'll keep playing with the script though.
I meant like this
# Add-PSSnapin vmware.vimautomation.core connect-viserver vspheredev $myCol = @() $mycol.Initialize() $vms = get-vm | where {$_.PowerState -eq "PoweredOn" -and $_.Guest.OSFullName -match "Microsoft Windows*" } | Sort Name foreach($vm in $vms) { Try { $wmi = get-wmiobject -class "Win32_DiskPartition" -namespace "root\CIMV2" -ComputerName $vm -ErrorAction silentlycontinue foreach ($objItem in $wmi) { if ($objItem.StartingOffset % 64kb -eq 0){ $Details = "" | Select-Object VMName, Disk, Partition, Offset, Status, VMDKPath
$Details.VMName = $vm.name $details.VMDKPath = $vm.HardDisks[0].Filename
$Details.Disk,$Details.Partition = $objItem.Name.Split(',') $details.offset = "$([long]$($objitem.StartingOffset)/1KB)KB"
$Details.Status = "Partition aligned" } else { $Details = "" | Select-Object VMName, Disk, Partition, Offset, Status, VMDKPath
$Details.VMName = $vm.name
$details.VMDKPath = $vm.HardDisks[0].Filename
$Details.Disk,$Details.Partition = $objItem.Name.Split(',') $details.offset = "$([long]$($objitem.StartingOffset)/1KB)KB"
$Details.Status = "Partition NOT aligned" } $myCol += $Details } } catch { $Details = "" | Select-Object VMName, Disk, Partition, Offset, Status, VMDKPath
$Details.VMName = $vm.name
$details.VMDKPath = ""
$Details.Disk = "error"
$Details.Partition = "error"
$details.offset = ""
$Details.Status = "error"
$myCol += $Details
} } $mycol | Export-Csv -NoTypeInformation "H:\Excel_Reports\NEW_Production_PartitionAlignment.csv"
#output errors to file $error >> "c:\temp\partition-check-errors.txt" $error.clear()
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I had to move some lines around but that did the trick.
As always... thanks again!
Would there be an easy way to add the wmiobject to get the OS?
The -class is different (its Win32_OperatingSystem) and the option would be .Caption.
Would I need to call the get-wmiobject all over again? I've tried to add a couple different options (See below) but I dont think Powershell lets you add one class?
$wmi = get-wmiobject -class "Win32_DiskPartition" , "Win32_OperatingSystem" -namespace "root\CIMV2" -ComputerName $vm -ErrorAction silentlycontinue
foreach ($objItem in $wmi)
Afaik the Class parameter on the Get-WMiObject cmdlet only accepts a [string], not an array [string[]].
So you would have to do 2 calls
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference