1

I'm trying to use Powershell to get SCSI hardware from several virtual servers and get the operating system of each specific server. I've managed to get the specific SCSI hardware that I want to find with my code, however I'm unable to figure out how to properly get the operating system of each of the servers. Also, I'm trying to send all the data that I find into a csv log file, however I'm unsure of how you can make a powershell script create multiple columns.

Here is my code (almost works but something's wrong):

$log = "C:\Users\me\Documents\Scripts\ScsiLog.csv"
Get-VM | Foreach-Object {
    $vm = $_
        Get-ScsiController -VM $vm | Where-Object { $_.Type -eq "VirtualBusLogic" } | Foreach-Object {
            get-VMGuest -VM $vm } | Foreach-Object{
        Write-output $vm.Guest.VmName  >> $log
            }
    }

I don't receive any errors when I run this code however whenever I run it I'm only getting the name of the servers and not the OS. Also I'm not sure what I need to do to make the OS appear in a different column from the name of the server in the csv log that I'm creating.

What do I need to change in my code to get the OS version of each virtual machine and output it in a different column in my csv log file?

EDIT: Here's a more in depth look at things I've tried that have all failed:

Get-VM | Foreach-Object {
    $vm = $_    
    $svm = Get-ScsiController -VM $vm | Where-Object { $_.Type -eq "VirtualBusLogic" } 
    Foreach-Object {get-VMGuest -VM $svm } | Foreach-Object{Write-output $svm >> $log}
    }

#Get-VM | Foreach-Object {
#   $vm = $_
#       Get-ScsiController -VM $vm | Where-Object { $_.Type -eq "VirtualBusLogic"} #| write-host $vm
#       | Foreach-Object {
#       
#       #get-VMGuest -VM $_ |
#       #write-host $vm
#           #get-VMGuest -VM $vm } | Foreach-Object{
#       #write-output $vm.VmName >> $log
#       #write-output $vm.guest.VmName, get-VmGuest -VM $vm >> $log NO GOOD
#
#       Write-host $vm.Guest.VmName #+ get-vmGuest -vm $VM >> $log
#
#
#       }
#   }

I'm not sure why get-VmGuest fails though. I'm getting the scsi hardware, filtering the hardware to only get buslogic, and then wanting to get the operating system of just the filtered VMs. I don't see where my code fails though.

Valrok
  • 330
  • 3
  • 11

2 Answers2

1

You were sort of on the right track until that last line, which is where it all goes wrong. Keep in mind that $_ dynamically changes value, whereas $vm keeps the same value that it got on line 3. Also, you're not really taking advantage of pipelining -- e.g. this: Get-VM | Get-ScsiController does the same thing as this:

Get-VM | Foreach-Object {
$vm = $_
Get-ScsiController -VM $vm 
}

I think the best way for you to get your report is to build an array with all of the data unfiltered, and then export it to a csv and do your filtering/grouping/etc in excel or whatever. This would be easy with just the above example, except that "OS Name" is not a property of the SCSI Controller object, so you need to loop through and get it. But then what to do with the result? There's no obvious place to store it. I chose to store it as an additional property of the SCSI Controller object:

$rows = @()
$log = "C:\Users\me\Documents\Scripts\ScsiLog.csv"
Get-VM | Get-ScsiController | ForEach-Object {
$row = $_
$os = (Get-VMGuest -vm $row.parent).OSFullName
$row | Add-Member -type NoteProperty -Name OS -Value $os
$rows += $row
}
$rows | select Type, Parent, OS | Export-CSV $log
1.618
  • 669
  • 1
  • 4
  • 17
  • Would I not be able to add my foreach filtering that I used to get only buslogic SCSI hardware or would that somehow change what gets returned? – Valrok Oct 18 '13 at 20:25
  • Yes, you could do that on line 2. You'd put the Where-Object before the ForEach-Object. I just left that out because I think it's more flexible that way, but that's just my preference. – 1.618 Oct 18 '13 at 20:33
  • Ok, as for performance since this script is being ran to look through several thousand VMs, would there be a performance increase by storing any values in arrays? I've considered looking for a faster method to improve the code (altho partly just haven't had the time since people above me just care to get a working script). – Valrok Oct 18 '13 at 20:37
  • Whether you store the results in an array or not is going to have a minimal impact on performance. Some of the PowerCLI cmdlets just seem to run slow, and I don't think there's much you can do about that. – 1.618 Oct 18 '13 at 20:42
  • Out of curiosity, what version of powerCLI do you use? Got the chance today to try running this and receive an error in that there's no method that contains op_addition (pretty much the += or if you try doing without the shortcut) – Valrok Oct 21 '13 at 17:32
  • When I pasted my code in, I somehow left off the first line, which defines $rows as an empty array. That's why you got that error. I edited my answer to include the missing line. – 1.618 Oct 21 '13 at 18:34
0

First, it looks like you've naively made some horrific nested loop by just cut-n-paste and replace. Think about the code flow. Why the third foreach statement?

For output : You really need to start learning Powershell, or rather, learning how to learn about powershell. Google and the MS site will help a lot, as will the built in help system. Pipe your whole thing into this (rather than doing an append in the middle of your loop)

Export-CSV $log

If you didn't know that, you could type get-help *csv* and find it.

mfinni
  • 35,711
  • 3
  • 50
  • 86