1 2 Previous Next 18 Replies Latest reply on May 25, 2020 2:17 AM by vin01

    update vm information in csv only which changed in vcenter

    vin01 Hot Shot

      I can able to get the complete information for every vms using the below script but its very tough to get csv exported for every week on large set of vms. so is it possible to append the existing csv with only changed vm information.

      Something like this.

      The script will be executed in scheduled task weekly once.

      1.At first instance below script will execute on all the vms at get the information updated in .csv

      2.When next week the scheduled task started it will check existing .csv and import all the information in a variable($importedvmsinfo)

      3.Next script will Get vCenter Events and match if any change done for the vms which are in $importedvmsinfo variable.

      4.then remove the row which is related to the vm in existing .csv and update the new information.

      Ex: At step 1 when one vm is powered on state and which is exported to .csv then when executed the script in next week at this point if the vms is powered off then update the latest information on the .csv by deleting the complete row related to that vm and create new row with latest information. (Same applies if vm memory updated,changes in hard disk or vm deleted).

      If nothing changed to the vm since 1 week then leave that row as it is in original csv file.

      foreach($vm in (Get-View -ViewType VirtualMachine -Property Name,runtime.powerState,Guest.net,Config.Hardware.numCPU,Config.Hardware.MemoryMB,Runtime.Host,Guest.GuestFullName,
      Config.GuestFullName,Parent,ResourcePool,Config.Hardware.Device,Config.version,guest.toolsversionstatus,
      Config.Files.VMPathName)){
          $t = Get-View $vm.ResourcePool -Property Name,Parent
          while($t.getType().Name -eq "ResourcePool"){
             $t = Get-View $t.Parent -Property Name,Parent
          }
              if($t.GetType().Name -eq "ClusterComputeResource"){
              $cluster = $t.Name
              }
              else{
                  $cluster = "Stand Alone Host"
              }
          while($t.getType().Name -ne "Datacenter"){
              $t = Get-View $t.Parent -Property Name,Parent
          }
          $datacenter = $t.Name
        
          $vm.Config.Hardware.Device | where {$_.GetType().Name -eq "VirtualDisk"} |
          Select @{N="vCenter";E={$script:vmhost = Get-View -Id $vm.Runtime.Host; $script:vmhost.Client.ServiceUrl.Split('/')[2]}},
          @{N="VM";E={$vm.Name}},
          @{N='powerState';E={$vm.runtime.powerState}},
          @{N='IP';E={[string]::Join(',',($vm.Guest.Net | %{$_.IpAddress | where{$_.Split('.').Count -eq 4} | %{$_}}))}},
          @{N='NumCPU';E={$vm.config.Hardware.NumCpu}},
          @{N='Memory GB';E={$vm.Config.Hardware.MemoryMB| %{[math]::Round($_/1kb,2)}}},
          @{N='VMHost';E={$script:esx = Get-View -Id $vm.Runtime.Host; $script:esx.name}},
          @{N='GuestOS';E={$vm.Guest.GuestFullName}},
          @{N='ConfiguredOS';E={$vm.Config.GuestFullName}},
          #@{N="Folder";E={$path}},
          @{N="Cluster";E={$cluster}},
          @{N="Datacenter";E={$datacenter}},
          @{N="Scsi";E={$_.UnitNumber}},
          @{N="Hard Disk";E={$_.DeviceInfo.Label}},
          @{N="Disk datastore";E={$_.Backing.Filename.Split(']')[0].TrimStart('[')}},
          @{N="Disk capacity GB";E={$_.CapacityInKB| %{[math]::Round($_/1MB,2)}}},
          @{N="Disk type";E={
                  if($_.Backing.GetType().Name -match "flat"){
                      "Flat"
                  }
                  else{
                      $_.Backing.CompatibilityMode
                  }}},
         @{N='DeviceName';E={
          if($_.Backing.GetType().Name -match 'raw'){
            $_.Backing.DeviceName
          }
          else{
            $script:lunnaa = (Get-View -Id $_.Backing.Datastore).Info.Vmfs.Extent[0].DiskName
            $script:lun = $script:esx.Config.StorageDevice.ScsiLun | where{$_.CanonicalName -eq $script:lunnaa}
            $script:lun.Descriptor | where{$_.Id -match 'vml.'} | Select -ExpandProperty Id
          }}},
         @{N='LUN NAA';E={
          if($_.Backing.GetType().Name -match 'raw'){
            $lunUuid = $_.Backing.LunUuid
            $script:lun = $script:esx.Config.StorageDevice.ScsiLun | where{$_.Uuid -eq $lunUuid}
            $script:lun.CanonicalName
          }
          else{
            $script:lunnaa
          }}},
         @{N='LUN ID';E={
            $dev = $script:esx.Config.StorageDevice.PlugStoreTopology.Device | where {$_.Lun -eq $script:lun.Key}
            $script:esx.Config.StorageDevice.PlugStoreTopology.Path | where {$_.Device -eq $dev.Key} |
            Select -First 1 -ExpandProperty LunNumber
          }},
         @{N='VMConfigFile';E={$VM.config.files.VMpathname}},
         @{N='VMDKPath';E={$_.Backing.FileName}},
         @{N="HW Version";E={$vm.Config.version}},
         @{N="Tools Status";E={$vm.guest.toolsversionstatus}},
         @{N="NIC Name";E={($vm.config.hardware.device | where {($_.DeviceInfo.Label -like "Network*")}).DeviceInfo.Label}},
         @{N="Mac"; E={($vm.Config.Hardware.Device | where{$_.DeviceInfo.Label -like "Network*"}).MacAddress}},
         @{N="Portgroup"; E={
           $nic = $vm.Config.Hardware.Device | where{$_.DeviceInfo.Label -like "Network*"}
           [string]::Join(',',(
             $nic | %{
             if($_.DeviceInfo.Summary -notmatch 'DVSwitch'){
               $_.DeviceInfo.Summary
             }
             else{
               Get-View -ViewType DistributedVirtualPortgroup -Property Name -Filter @{'Key'=$_.Backing.Port.PortgroupKey} |
               Select -ExpandProperty Name
             }}))}}
      }
      
      Regards
      Vineeth.K
        • 1. Re: update vm information in csv only which changed in vcenter
          LucD Guru
          Community WarriorsUser ModeratorsvExpert

          Perhaps I'm misunderstanding your intention here, but isn't this just the same as overwriting the same CSV on each run?

          Blog: http://lucd.info | Twitter: @LucD22 | PowerCLI Reference co-author: http://tinyurl.com/hkn4glz
          • 2. Re: update vm information in csv only which changed in vcenter
            vin01 Hot Shot

            Yes LucD I’m looking to overwrite the existing csv by replacing the older information in the csv. If excel works better then csv then I’ll use excel itself.

             

            If overwrite is not Possible then import the data from the existing csv and look for changes in the vms and create a new csv with latest date.

            if nothing is changed for the vms from past 1 week then write the same imported data into new csv or just rename the existing csv with new date.

            Regards
            Vineeth.K
            • 3. Re: update vm information in csv only which changed in vcenter
              LucD Guru
              User ModeratorsvExpertCommunity Warriors

              Perhaps I didn't explain my question correctly, but if this is a fixed environment (same VMs all the time), you can just completely overwrite the CSV file each run.

               

              If VMs are added and removed, and you want to keep the removed VMs in the CSV, then this would not work with just overwriting the CSV file.

               

              Assume the first CSV contains

               

              VM,CPU

              vm1,2

              vm2,4

               

              Then next week the CPUs on VM2 are changed, so you just overwrite the file

               

              VM,CPU

              vm1,2

              vm2,2

               

              But if VMs are added and removed, and you want to keep removed VMs in the CSV, another approach is required.

               

              VM,CPU

              vm1,2
              vm2,2

               

              Now VM1 is removed and a new VM3 is introduced.
              Should the CSV be

               

              VM,CPU

              vm2,2

              vm3,4

               

              or

               

              VM,CPU

              vm1,2

              vm2,2

              vm3,4

              Blog: http://lucd.info | Twitter: @LucD22 | PowerCLI Reference co-author: http://tinyurl.com/hkn4glz
              • 4. Re: update vm information in csv only which changed in vcenter
                vin01 Hot Shot

                Oh I got your question now.

                In my original question the point I missed to explain is what if new vm is created or existing deleted.

                I’m expecting any way as below.

                 

                VM,CPU,comment

                vm1,2,vm is removed(or no data available)

                vm2,2

                vm3,4,new vm added on this date


                If above doesn’t makes sense then below also works for me.

                At first week execution sheet is like this

                VM,CPU

                vm1,2

                vm2,4


                second week execution create a new csv with latest date and write as below.Here it should get only the information for vm3 from vcenter as this is newly created and vc events shows this newly created event.

                VM,CPU

                vm1,2

                vm2,2

                vm3,4

                 

                Third week execution create a new csv with latest date and write as below.Here it should get only the information for vm1 from vcenter as there is change in cpu and vc events shows this.

                VM,CPU

                vm1,4

                vm2,2

                vm3,4


                if the vc events doesn’t shows what has changed exactly but only the event says reconfigure is done then the script should get the complete information of that vm.

                 

                 

                 

                 

                Basically what I’m looking is the script should avoid checking each and every vms information every week. Only changes should be updated. it will reduce the execution time when running on larger environment.

                 

                Hope my explanation understands the whole question.

                Regards
                Vineeth.K
                • 5. Re: update vm information in csv only which changed in vcenter
                  LucD Guru
                  vExpertUser ModeratorsCommunity Warriors

                  Ok, just to make sure I understand what you are saying.

                   

                  The script shall be based on events from the last week.

                  The events that need to be looked at are 'a VM is created', 'a VM is removed' and 'a VM is reconfigured'.

                  Only for those VMs the CSV needs to be updated.


                  Which means:

                  - add VMs that were added over the last week

                  - remove VMs that are deleted over the last week

                  - change the entries for VMs that were reconfigured over the last week

                   

                  Correct?

                  Blog: http://lucd.info | Twitter: @LucD22 | PowerCLI Reference co-author: http://tinyurl.com/hkn4glz
                  • 6. Re: update vm information in csv only which changed in vcenter
                    vin01 Hot Shot

                    Yes you are right. I believe the expected output will contains the complete information of the vm right?

                    Like name,ip,powerstate etc.. which are there in the original script.

                    Regards
                    Vineeth.K
                    • 7. Re: update vm information in csv only which changed in vcenter
                      LucD Guru
                      User ModeratorsvExpertCommunity Warriors

                      The script is a bit more complex than I considered originally.

                      And that is because you can have more than 1 entry per VM, since you make a row per VM/HardDisk.

                       

                      The first time the script runs, when there is no CSV file, it will collect all data.

                      Subsequent runs will update the CSV depending on the events that were detected.

                       

                      Note that you have to look at events since exactly the time the script ran the last time.

                      Otherwise the CSV might become incorrect.

                       

                      function Get-VMInfo {

                          param(

                              [string]$Name

                          )


                          $vm = Get-View -ViewType VirtualMachine -Property Name, runtime.powerState, Guest.net, Config.Hardware.numCPU, Config.Hardware.MemoryMB, Runtime.Host, Guest.GuestFullName,

                          Config.GuestFullName, Parent, ResourcePool, Config.Hardware.Device, Config.version, guest.toolsversionstatus,

                          Config.Files.VMPathName -filter @{'Name' = "^$Name$" }

                          if ($vm) {

                              $t = Get-View $vm.ResourcePool -Property Name, Parent

                              while ($t.getType().Name -eq "ResourcePool") {

                                  $t = Get-View $t.Parent -Property Name, Parent

                              }

                              if ($t.GetType().Name -eq "ClusterComputeResource") {

                                  $cluster = $t.Name

                              } else {

                                  $cluster = "Stand Alone Host"

                              }

                              while ($t.getType().Name -ne "Datacenter") {

                                  $t = Get-View $t.Parent -Property Name, Parent

                              }

                              $datacenter = $t.Name

                        

                              $vm.Config.Hardware.Device | Where-Object { $_.GetType().Name -eq "VirtualDisk" } |

                              Select-Object @{N = "vCenter"; E = { $script:vmhost = Get-View -Id $vm.Runtime.Host; $script:vmhost.Client.ServiceUrl.Split('/')[2] } },

                              @{N = "VM"; E = { $vm.Name } },

                              @{N = 'powerState'; E = { $vm.runtime.powerState } },

                              @{N = 'IP'; E = { [string]::Join(',', ($vm.Guest.Net | ForEach-Object { $_.IpAddress | Where-Object { $_.Split('.').Count -eq 4 } | ForEach-Object { $_ } })) } },

                      @{N = 'NumCPU'; E = { $vm.config.Hardware.NumCpu } },

                      @{N = 'Memory GB'; E = { $vm.Config.Hardware.MemoryMB | ForEach-Object { [math]::Round($_/1kb, 2) } } },

                      @{N = 'VMHost'; E = { $script:esx = Get-View -Id $vm.Runtime.Host; $script:esx.name } },

                      @{N = 'GuestOS'; E = { $vm.Guest.GuestFullName } },

                      @{N = 'ConfiguredOS'; E = { $vm.Config.GuestFullName } },

                      #@{N="Folder";E={$path}}, 

                      @{N = "Cluster"; E = { $cluster } },

                      @{N = "Datacenter"; E = { $datacenter } },

                      @{N = "Scsi"; E = { $_.UnitNumber } },

                      @{N = "Hard Disk"; E = { $_.DeviceInfo.Label } },

                      @{N = "Disk datastore"; E = { $_.Backing.Filename.Split(']')[0].TrimStart('[') } },

                      @{N = "Disk capacity GB"; E = { $_.CapacityInKB | ForEach-Object { [math]::Round($_/1MB, 2) } } },

                      @{N = "Disk type"; E = {

                              if ($_.Backing.GetType().Name -match "flat") {

                                  "Flat"

                              } else {

                                  $_.Backing.CompatibilityMode

                              } }

                      },

                      @{N = 'DeviceName'; E = {

                              if ($_.Backing.GetType().Name -match 'raw') {

                                  ($_.Backing.DeviceName) -join '|'

                              } else {

                                  $script:lunnaa = (Get-View -Id $_.Backing.Datastore).Info.Vmfs.Extent[0].DiskName

                                  $script:lun = $script:esx.Config.StorageDevice.ScsiLun | Where-Object { $_.CanonicalName -eq $script:lunnaa }

                              $script:lun.Descriptor | Where-Object { $_.Id -match 'vml.' } | Select-Object -ExpandProperty Id

                      } }

                      },

                      @{N = 'LUN NAA'; E = {

                              if ($_.Backing.GetType().Name -match 'raw') {

                                  $lunUuid = $_.Backing.LunUuid

                                  $script:lun = $script:esx.Config.StorageDevice.ScsiLun | Where-Object { $_.Uuid -eq $lunUuid }

                              $script:lun.CanonicalName

                          } else {

                              $script:lunnaa

                          } }

                      },

                      @{N = 'LUN ID'; E = {

                              $dev = $script:esx.Config.StorageDevice.PlugStoreTopology.Device | Where-Object { $_.Lun -eq $script:lun.Key }

                          $script:esx.Config.StorageDevice.PlugStoreTopology.Path | Where-Object { $_.Device -eq $dev.Key } |

                          Select-Object -First 1 -ExpandProperty LunNumber

                      }

                      },

                      @{N = 'VMConfigFile'; E = { $VM.config.files.VMpathname } },

                      @{N = 'VMDKPath'; E = { $_.Backing.FileName } },

                      @{N = "HW Version"; E = { $vm.Config.version } },

                      @{N = "Tools Status"; E = { $vm.guest.toolsversionstatus } },

                      @{N = "NIC Name"; E = { ($vm.config.hardware.device | Where-Object { ($_.DeviceInfo.Label -like "Network*") }).DeviceInfo.Label } },

                      @{N = "Mac"; E = { ($vm.Config.Hardware.Device | Where-Object { $_.DeviceInfo.Label -like "Network*" }).MacAddress } },

                      @{N = "Portgroup"; E = {

                              $nic = $vm.Config.Hardware.Device | Where-Object { $_.DeviceInfo.Label -like "Network*" }

                          [string]::Join(',', (

                                  $nic | ForEach-Object {

                                      if ($_.DeviceInfo.Summary -notmatch 'DVSwitch') {

                                          $_.DeviceInfo.Summary

                                      } else {

                                          Get-View -ViewType DistributedVirtualPortgroup -Property Name -Filter @{'Key' = $_.Backing.Port.PortgroupKey } |

                                              Select-Object -ExpandProperty Name

                                      } })) }

                      }

                      }

                      }


                      $fileName = '.\VMreport.csv'


                      $eventTypes = 'VmReconfiguredEvent', 'VmRemovedEvent', 'VmDeployedEvent'

                      $start = (Get-Date).AddDays(-1)


                      $hash = @{ }


                      if (Test-Path -Path $fileName) {

                          Import-Csv -Path .\VMreport.csv -UseCulture |

                              ForEach-Object -Process {

                                  $hash.Add("$($_.VM)$($_.'Hard Disk')", $_)

                              }


                          Get-VIEvent -Start $start -MaxSamples ([int]::MaxValue) |

                              Where-Object { $eventTypes -contains ($_.GetType()).FullName.Split('.')[2] } |

                              Group-Object -Property { $_.VM.Name } |

                              ForEach-Object -Process {

                                  Write-Host "Looking at $($_.Name)"

                                  $_.Group | Sort-Object -Property CreatedTime |

                                  ForEach-Object -Process {

                                      $event = $_

                                      switch ($event.GetType().FullName.Split('.')[2]) {

                                          'VmRemovedEvent' {

                                              $hash.GetEnumerator() | Where-Object { $_.Key -match "^$($event.VM.Name)" } |

                                              ForEach-Object -Process {

                                                  $hash.Remove("$($_.VM)$($_.'Hard Disk')")

                                              }

                                      }

                                      'VmDeployedEvent' {

                                          Get-VMInfo -Name $event.VM.Name |

                                              ForEach-Object -Process {

                                                  $hash.Add("$($_.VM)$($_.'Hard Disk')", $_)

                                              }

                                      }

                                      'VmReconfiguredEvent' {

                                          Get-VMInfo -Name $event.VM.Name |

                                              ForEach-Object -Process {

                                                  $hash.Item("$($_.VM)$($_.'Hard Disk')") = $_

                                              }

                                      }

                                  }

                              }

                      }

                      } else {

                          Get-View -ViewType Virtualmachine -Property Name -Filter @{'Config.Template' = 'False' } |

                              ForEach-Object -Process {

                                  Write-Host "Looking at $($_.Name)"

                                  Get-VMInfo -Name $_.Name |

                                      ForEach-Object -Process {

                                          $hash.Add("$($_.VM)$($_.'Hard Disk')", $_)

                                      }

                              }

                      }


                      $hash.Values | Export-Csv -Path $fileName -NoTypeInformation -UseCulture

                      Blog: http://lucd.info | Twitter: @LucD22 | PowerCLI Reference co-author: http://tinyurl.com/hkn4glz
                      1 person found this helpful
                      • 8. Re: update vm information in csv only which changed in vcenter
                        vin01 Hot Shot

                        I just tested in my environment with small set of vms in a vcenter. At first execution the vms are in powered on state and I got the report in csv then I powered off the vms and done changes like adding harddisk and changing cpu & memory for few vms.

                        I have changed $start = (Get-Date).AddMinutes(-3) in the script and retried after 15 mins but the changes are not recorded in the csv.

                        Should I need to change any other parameter to do a quick check?

                        Regards
                        Vineeth.K
                        • 9. Re: update vm information in csv only which changed in vcenter
                          LucD Guru
                          vExpertCommunity WarriorsUser Moderators

                          The changes are based on the events that are listed in $eventTypes, other changes, like power off, will not be captured.

                          And to be honest, that is not what I understood from your original question.

                           

                          You have to capture all events that happened after the 1st run of the script.

                          So you $start datetime should in fact be the time your first run finished.

                          Blog: http://lucd.info | Twitter: @LucD22 | PowerCLI Reference co-author: http://tinyurl.com/hkn4glz
                          • 10. Re: update vm information in csv only which changed in vcenter
                            vin01 Hot Shot

                            The changes are based on the events that are listed in $eventTypes, other changes, like power off, will not be captured.

                            And to be honest, that is not what I understood from your original question.

                            sorry it was miss from my side.

                            i thought VmReconfiguredEvent will contains poweroff,addition of hard disk and any change in network port.

                            Can we add events like poweroff addition of hard disk and any change in network portgroup.

                             

                            You have to capture all events that happened after the 1st run of the script.

                            So you $start datetime should in fact be the time your first run finished.

                            Understood. will it fix if we do something like this

                            At the first run of the script if we capture date and time in the csv and in second run we can check the events which are generated between the current time and time which is in csv file. And while updating the vms change results we can also update the new time stamp in csv file.

                            Regards
                            Vineeth.K
                            • 11. Re: update vm information in csv only which changed in vcenter
                              LucD Guru
                              vExpertCommunity WarriorsUser Moderators

                              The power off/power on will not be captured by a VmReconfiguredEvent.

                              These actions have other events: VmPoweredOff and VmPoweredOn.

                              Adding a harddisk or changing a vNIC config should result in a VmReconfiguredEvent, and thus should be captured.

                               

                              A CSV is a rather flat structure and it can only have 1 type of row in there.

                              That would mean the datetime would appear in every row in the CSV, which is a lot of redundant data.

                              You could consider kind of config file next to the CSV.

                              There the script could write the datatime of the last run.

                              Blog: http://lucd.info | Twitter: @LucD22 | PowerCLI Reference co-author: http://tinyurl.com/hkn4glz
                              1 person found this helpful
                              • 12. Re: update vm information in csv only which changed in vcenter
                                vin01 Hot Shot

                                You could consider kind of config file next to the CSV.

                                There the script could write the datatime of the last run.

                                config file means a .txt file which contains date and time which will be in the same location where csv file exist? If that the thing expected if so I will then maintain it.

                                can you pls update the code With the creation of config txt file and the VmPoweredOff and VmPoweredOn Events.

                                Regards
                                Vineeth.K
                                • 13. Re: update vm information in csv only which changed in vcenter
                                  LucD Guru
                                  vExpertUser ModeratorsCommunity Warriors

                                  Ok, this version includes power on/power off events.

                                  The file containing the date of the last run has the same name as the CSV file, except the type is .cfg.

                                   

                                  function Get-VMInfo {

                                      param(

                                          [string]$Name

                                      )


                                      $vm = Get-View -ViewType VirtualMachine -Property Name, runtime.powerState, Guest.net, Config.Hardware.numCPU, Config.Hardware.MemoryMB, Runtime.Host, Guest.GuestFullName,

                                      Config.GuestFullName, Parent, ResourcePool, Config.Hardware.Device, Config.version, guest.toolsversionstatus,

                                      Config.Files.VMPathName -filter @{'Name' = "^$Name$" }

                                      if ($vm) {

                                          $t = Get-View $vm.ResourcePool -Property Name, Parent

                                          while ($t.getType().Name -eq "ResourcePool") {

                                              $t = Get-View $t.Parent -Property Name, Parent

                                          }

                                          if ($t.GetType().Name -eq "ClusterComputeResource") {

                                              $cluster = $t.Name

                                          } else {

                                              $cluster = "Stand Alone Host"

                                          }

                                          while ($t.getType().Name -ne "Datacenter") {

                                              $t = Get-View $t.Parent -Property Name, Parent

                                          }

                                          $datacenter = $t.Name

                                    

                                          $vm.Config.Hardware.Device | Where-Object { $_.GetType().Name -eq "VirtualDisk" } |

                                          Select-Object @{N = "vCenter"; E = { $script:vmhost = Get-View -Id $vm.Runtime.Host; $script:vmhost.Client.ServiceUrl.Split('/')[2] } },

                                          @{N = "VM"; E = { $vm.Name } },

                                          @{N = 'powerState'; E = { $vm.runtime.powerState } },

                                          @{N = 'IP'; E = { [string]::Join(',', ($vm.Guest.Net | ForEach-Object { $_.IpAddress | Where-Object { $_.Split('.').Count -eq 4 } | ForEach-Object { $_ } })) } },

                                  @{N = 'NumCPU'; E = { $vm.config.Hardware.NumCpu } },

                                  @{N = 'Memory GB'; E = { $vm.Config.Hardware.MemoryMB | ForEach-Object { [math]::Round($_/1kb, 2) } } },

                                  @{N = 'VMHost'; E = { $script:esx = Get-View -Id $vm.Runtime.Host; $script:esx.name } },

                                  @{N = 'GuestOS'; E = { $vm.Guest.GuestFullName } },

                                  @{N = 'ConfiguredOS'; E = { $vm.Config.GuestFullName } },

                                  #@{N="Folder";E={$path}}, 

                                  @{N = "Cluster"; E = { $cluster } },

                                  @{N = "Datacenter"; E = { $datacenter } },

                                  @{N = "Scsi"; E = { $_.UnitNumber } },

                                  @{N = "Hard Disk"; E = { $_.DeviceInfo.Label } },

                                  @{N = "Disk datastore"; E = { $_.Backing.Filename.Split(']')[0].TrimStart('[') } },

                                  @{N = "Disk capacity GB"; E = { $_.CapacityInKB | ForEach-Object { [math]::Round($_/1MB, 2) } } },

                                  @{N = "Disk type"; E = {

                                          if ($_.Backing.GetType().Name -match "flat") {

                                              "Flat"

                                          } else {

                                              $_.Backing.CompatibilityMode

                                          } }

                                  },

                                  @{N = 'DeviceName'; E = {

                                          if ($_.Backing.GetType().Name -match 'raw') {

                                              ($_.Backing.DeviceName) -join '|'

                                          } else {

                                              $script:lunnaa = (Get-View -Id $_.Backing.Datastore).Info.Vmfs.Extent[0].DiskName

                                              $script:lun = $script:esx.Config.StorageDevice.ScsiLun | Where-Object { $_.CanonicalName -eq $script:lunnaa }

                                          $script:lun.Descriptor | Where-Object { $_.Id -match 'vml.' } | Select-Object -ExpandProperty Id

                                  } }

                                  },

                                  @{N = 'LUN NAA'; E = {

                                          if ($_.Backing.GetType().Name -match 'raw') {

                                              $lunUuid = $_.Backing.LunUuid

                                              $script:lun = $script:esx.Config.StorageDevice.ScsiLun | Where-Object { $_.Uuid -eq $lunUuid }

                                          $script:lun.CanonicalName

                                      } else {

                                          $script:lunnaa

                                      } }

                                  },

                                  @{N = 'LUN ID'; E = {

                                          $dev = $script:esx.Config.StorageDevice.PlugStoreTopology.Device | Where-Object { $_.Lun -eq $script:lun.Key }

                                      $script:esx.Config.StorageDevice.PlugStoreTopology.Path | Where-Object { $_.Device -eq $dev.Key } |

                                      Select-Object -First 1 -ExpandProperty LunNumber

                                  }

                                  },

                                  @{N = 'VMConfigFile'; E = { $VM.config.files.VMpathname } },

                                  @{N = 'VMDKPath'; E = { $_.Backing.FileName } },

                                  @{N = "HW Version"; E = { $vm.Config.version } },

                                  @{N = "Tools Status"; E = { $vm.guest.toolsversionstatus } },

                                  @{N = "NIC Name"; E = { ($vm.config.hardware.device | Where-Object { ($_.DeviceInfo.Label -like "Network*") }).DeviceInfo.Label -join '|' } },

                                  @{N = "Mac"; E = { ($vm.Config.Hardware.Device | Where-Object { $_.DeviceInfo.Label -like "Network*" }).MacAddress -join '|' } },

                                  @{N = "Portgroup"; E = {

                                          $nic = $vm.Config.Hardware.Device | Where-Object { $_.DeviceInfo.Label -like "Network*" }

                                      [string]::Join(',', (

                                              $nic | ForEach-Object {

                                                  if ($_.DeviceInfo.Summary -notmatch 'DVSwitch') {

                                                      $_.DeviceInfo.Summary

                                                  } else {

                                                      Get-View -ViewType DistributedVirtualPortgroup -Property Name -Filter @{'Key' = $_.Backing.Port.PortgroupKey } |

                                                          Select-Object -ExpandProperty Name

                                                  } })) }

                                  }

                                  }

                                  }


                                  $fileName = '.\VMreport.csv'


                                  $configFile = $fileName.Replace('.csv', '.cfg')

                                  $eventTypes = 'VmReconfiguredEvent', 'VmRemovedEvent', 'VmDeployedEvent', 'VmPoweredOffEvent', 'VmPoweredOnEvent'

                                  $start = (Get-Date).AddDays(-1)


                                  $hash = @{ }

                                  $now = Get-Date


                                  if (Test-Path -Path $fileName) {

                                      Import-Csv -Path .\VMreport.csv -UseCulture |

                                          ForEach-Object -Process {

                                              $hash.Add("$($_.VM)$($_.'Hard Disk')", $_)

                                          }

                                      $start = [DateTime](Get-Content -Path $configFile)

                                      Get-VIEvent -Start $start -MaxSamples ([int]::MaxValue) |

                                          Where-Object { $eventTypes -contains ($_.GetType()).FullName.Split('.')[2] -or $eventTypes -contains ($_.GetType()).BaseType.Name } |

                                          Group-Object -Property { $_.VM.Name } |

                                          ForEach-Object -Process {

                                              Write-Host "Looking at $($_.Name)"

                                              $_.Group | Sort-Object -Property CreatedTime |

                                              ForEach-Object -Process {

                                                  $event = $_

                                                  switch ($event.GetType().FullName.Split('.')[2]) {

                                                      'VmRemovedEvent' {

                                                          $hash.GetEnumerator() | Where-Object { $_.Key -match "^$($event.VM.Name)" } |

                                                          ForEach-Object -Process {

                                                              $hash.Remove("$($_.VM)$($_.'Hard Disk')")

                                                          }

                                                  }

                                                  'VmDeployedEvent' {

                                                      Get-VMInfo -Name $event.VM.Name |

                                                          ForEach-Object -Process {

                                                              $hash.Add("$($_.VM)$($_.'Hard Disk')", $_)

                                                          }

                                                  }

                                                  'VmReconfiguredEvent' {

                                                      Get-VMInfo -Name $event.VM.Name |

                                                          ForEach-Object -Process {

                                                              $hash.Item("$($_.VM)$($_.'Hard Disk')") = $_

                                                          }

                                                  }

                                                  'VmPoweredOnEvent' {

                                                      $rows = $hash.GetEnumerator() | Where-Object { $_.Key -match "^$($event.VM.Name)" }

                                                  $rows | ForEach-Object -Process {

                                                      $_.Value.PowerState = 'poweredOn'

                                                      $hash.Item($_.Key) = $_.Value

                                                  }

                                          }

                                          'VmPoweredOffEvent' {

                                              $rows = $hash.GetEnumerator() | Where-Object { $_.Key -match "^$($event.VM.Name)" }

                                          $rows | ForEach-Object -Process {

                                              $_.Value.PowerState = 'poweredOff'

                                              $hash.Item($_.Key) = $_.Value

                                          }

                                  }

                                  }

                                  }

                                  }

                                  } else {

                                      Get-View -ViewType Virtualmachine -Property Name -Filter @{'Config.Template' = 'False' } |

                                          ForEach-Object -Process {

                                              Write-Host "Looking at $($_.Name)"

                                              Get-VMInfo -Name $_.Name |

                                                  ForEach-Object -Process {

                                                      $hash.Add("$($_.VM)$($_.'Hard Disk')", $_)

                                                  }

                                          }

                                  }


                                  $hash.Values | Export-Csv -Path $fileName -NoTypeInformation -UseCulture

                                  $now.ToString() | Out-File -FilePath $configFile

                                  Blog: http://lucd.info | Twitter: @LucD22 | PowerCLI Reference co-author: http://tinyurl.com/hkn4glz
                                  1 person found this helpful
                                  • 14. Re: update vm information in csv only which changed in vcenter
                                    vin01 Hot Shot

                                    I have tested the script in my environment by changing to $start = (Get-Date).AddMinutes(-1)

                                    Test was done by executing once in hour by  powering off ,adding the disk and creating new vms

                                    What I observed is re configuring task(like changing memory and cpu) and new harddisk creation is updating the .csv

                                    when new harddisk is added to particular vm then the vm information is not in sequence in .csv. Can it be fixed to get in sequence?

                                    Something like this:

                                    Name Harddisk

                                    VM01     harddisk1

                                    VM02     harddisk1

                                    VM01     harddisk2

                                     

                                    Poweron/off and new vm creation tasks are not updating in the sheet.

                                    Regards
                                    Vineeth.K
                                    1 2 Previous Next