Author Posts

December 27, 2017 at 12:52 am

Hey all, hope you all have good Christmas/Holiday.

I'm creating a tool to capture data from vSphere for any of our VM's so we have a point in time snapshot of the current set up prior to actioning any change on that VM. This data is exported to csv and attached to the change as part of the pre checks in case of roll back. I have sub tools that capture different elements of the VM (Hardware config, Storage config, IP config etc.) and want to combine them together in one object (if possible) so that we can then feed that info to other tools or exported to csv giving us one line per VM with all of its parts.
Now if the VM has one IP Address and one Hard Disk this is simple. I can create the one object and everyone is happy. However VMs can have multiple IPs and multiple disks. Below are the examples of the output for Server 1 (One Hard Disk), Server 2 (Three Hard Disks) and one non existent vm (bob) which outputs a blank object

##Basic VM info

PS C:\> Get-vSphereVMData -ComputerName server1,server2,bob

VMName     : server1
Status     : True
PowerState : PoweredOn
vCpu       : 2
MemoryGB   : 4
Datastore  : LUN01
VMXFile    : [LUN01] server1/server1.vmx
vCenter    : vc01
Host       : esx01.operations.local
OS         : Microsoft Windows Server 2012 (64-bit)

VMName     : server2
Status     : True
PowerState : PoweredOn
vCpu       : 4
MemoryGB   : 12
Datastore  : LUN01
VMXFile    : [LUN01] server2/server2.vmx
vCenter    : vc01
Host       : esx01.operations.local
OS         : Microsoft Windows Server 2012 (64-bit)

vAppName   : bob
Status     : False
PowerState :
vCpu       :
MemoryGB   :
Datastore  :
VMXFile    :
vCenter    :
Host       :
OS         :

##Hard disk configuration per vm

PS C:\> Get-vSphereVMStorageData -ComputerName server1,server2,bob

VM         : server1
Status     : True
SCSI       : 0:0
HD         : Hard disk 1
Label      : SCSI controller 0
SCSIType   : LSI Logic
Filename   : [LUN01] server1/server1_1.vmdk
CapacityGB : 64

VM         : server2
Status     : True
SCSI       : 0:0
HD         : Hard disk 1
Label      : SCSI controller 0
SCSIType   : LSI Logic SAS
Filename   : [LUN01] server2/server2.vmdk
CapacityGB : 60

VM         : server2
Status     : True
SCSI       : 0:1
HD         : Hard disk 3
Label      : SCSI controller 0
SCSIType   : LSI Logic SAS
Filename   : [LUN01] server2/server2_2.vmdk
CapacityGB : 100

VM         : server2
Status     : True
SCSI       : 1:0
HD         : Hard disk 2
Label      : SCSI controller 1
SCSIType   : LSI Logic SAS
Filename   : [LUN01] server2/server2_1.vmdk
CapacityGB : 200

WARNING: Errors happened when attempting to find VM bob in vc01
VM         : bob
Status     : False
SCSI       :
HD         :
Label      :
SCSIType   :
Filename   :
CapacityGB :

I'm foreaching through each disk and grabbing the data I need and outputting one object per disk. Server 1 has one disk, Serer 2 has three disks and bob does not exist.

The thing that is screwing with my head, is stitching the data together per server. Like i said above it's easy when the VM has one disk but i can't figure out how to handle if a VM has multiple disks. Looking at the the max number of disks a VM can have it can be up to 64 disks. (BTW this question is only looking at disks but i am also having the same problem with multiple IP/Network cards too). Am i going in the right direction with an expanding object (if that's even possible) or am i diving down a Inception rabbit hole going the wrong direction?

December 27, 2017 at 4:57 pm

Hey Alex-

To my understanding, if a VM has multiple values for one property you would like to make a custom object containing all those values. Now I cant say that I have the perfect solution for you; however, I was in a similar situation when trying to query active directory users and grab their memberships to export to csv with all group names in separate cells. While exporting to a csv, all the objects must contain the same header quantity and header names in order for this to work. So If I had one user with 23 memberships then all new custom objects I was generating needed to have 23 membership fields. I solved this by gathering the number of groups each user was apart of and just storing the count value in an array and then grabbing the highest number (fig 1). From there, I would create the custom psObject and then run it through a for loop to add new custom note properties equal to the highest number of group memberships (Fig 2). Finally I would start filling in the data gathered, using another for loop. Once again, not saying this is your solution or the best one but maybe it can help get you moving in the right direction.

Fig 1.

$adUsers = Get-ADUser -Filter * -Properties DisplayName, SamAccountName, Enabled, MemberOf

$memberCount = @()
Foreach ($a in $adUsers) {
    $memberCount += $a.MemberOf.Count
}

$count = $memberCount | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum

Fig 2.

$result = @()
ForEach ($a in $adUsers) {
    $groupName = $a.MemberOf | Get-ADGroup | Select -ExpandProperty Name 
    # Create new psObject. [ordered] was a life saver because hashtables dont retain property order.
    $obj = New-Object psobject -Property ([ordered] @{

            DisplayName = $a.DisplayName
            SamAccount  = $a.SamAccountName
            Enabled     = $a.Enabled
            Group       = $groupName | Select -First 1
        })
    # Create new alias properties based on the number stored in $count variable
    For ($i = 0; $i -lt $count; $i++) {
        $obj | Add-Member -MemberType NoteProperty -Name "Group_$i" -Value $null -Force
    }

December 27, 2017 at 10:28 pm

Thanks Michael that has put me in a good direction. I'll let you know how i go.