VMware Cloud Community
justinsmith
Enthusiast
Enthusiast
Jump to solution

Misaligned VMDK's Powercli Script Help

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:

VMNamePartitionOffsetStatus
pdxvvmdb1Disk #0, Partition #18193150KBPartition NOT aligned
pdxvvmdb1Disk #0, Partition #18193150KBPartition 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....

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

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

View solution in original post

Reply
0 Kudos
22 Replies
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
justinsmith
Enthusiast
Enthusiast
Jump to solution

Brilliant.... what about the VM's that actually have multiple VMDK's though? Will it list out all, if any?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
justinsmith
Enthusiast
Enthusiast
Jump to solution

Good to know.

It still doesnt look like the script is getting the right data though. For instance, output data:

VMNamePartitionOffsetStatus
seavvafile2Disk #1, Partition #032KBPartition NOT aligned
seavvafile2Disk #1, Partition #032KBPartition 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.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Didn't you get the VMDKPath property ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I just tested on a VM with 4 VMDK and 2 partitions on the first disk.

Looked ok to me

align.png


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
justinsmith
Enthusiast
Enthusiast
Jump to solution

I had to play around with the script you pasted... running it now to see what it comes up with.

Reply
0 Kudos
justinsmith
Enthusiast
Enthusiast
Jump to solution

Is yours outputting the proper VMDK path?

jsmith1Disk #1, Partition #031.5KBPartition NOT aligned[DS1] jsmith1/jsmith1.vmdk
jsmith1Disk #1, Partition #031.5KBPartition 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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
justinsmith
Enthusiast
Enthusiast
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That back-tick had to go, I updated the code above


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
justinsmith
Enthusiast
Enthusiast
Jump to solution

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!

Reply
0 Kudos
justinsmith
Enthusiast
Enthusiast
Jump to solution

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.....

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
justinsmith
Enthusiast
Enthusiast
Jump to solution

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.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
justinsmith
Enthusiast
Enthusiast
Jump to solution

I had to move some lines around but that did the trick.

As always... thanks again!

Reply
0 Kudos
justinsmith
Enthusiast
Enthusiast
Jump to solution

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)

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos