VMware Cloud Community
PSScripter
Enthusiast
Enthusiast

Why does my script never complete?

Hello folks,

I have this script that was working at 1 point, I modified it to try and collect the information from just some clusters in txt file, but the script never ends. Any idea what Im doing wrong?

 

$array = @()
$vc = Get-Content 'C:\temp\vSphere\vcs.txt'
$clusters = Get-Content 'C:\temp\vSphere\clusters.txt'



foreach ($v in $vc) {
    Connect-VIServer $v -Force
}
$vms = Get-Cluster $clusters | Get-VM -ErrorAction SilentlyContinue
   
foreach ($cluster in $clusters) {
    
    foreach ($vm in $vms) {
   
        $ds = Get-VM $vm | Select-Object @{N = "Datastore"; E = { Get-Datastore -vm $_ } }
        $disks = $vm | Get-ScsiController | Where-Object { $_.BusSharingMode -eq 'Physical' -or $_.BusSharingMode -eq 'Virtual' }
        foreach ($disk in $disks) {

            $REPORT = New-Object -TypeName PSObject
            $REPORT | Add-Member -type NoteProperty -name ClusterName -Value $cluster
            $REPORT | Add-Member -type NoteProperty -name Name -Value $vm.Name
            $REPORT | Add-Member -type NoteProperty -name VMHost -Value $vm.VMHost
            $REPORT | Add-Member -type NoteProperty -name Mode -Value $disk.BusSharingMode
            $REPORT | Add-Member -type NoteProperty -name Type -Value 'BusSharing'
            $REPORT | Add-Member -type NoteProperty -name Datastore -Value $ds
            $array += $REPORT
        }
    }
}
    
$array | Export-Csv "C:\temp\Get-SCSIBusSharingVMs-Output.csv"

 

Thanks for any input!

Reply
0 Kudos
12 Replies
LucD
Leadership
Leadership

I don't see why your script would run forever.
But I do see why it could run for a very long time.

In this line, you are getting all the VMs for all the Clusters for all the vCenters.

$vms = Get-Cluster $clusters | Get-VM -ErrorAction SilentlyContinue


Then you have a loop over all the clusters, and for each cluster you loop over all the VMs.

foreach ($cluster in $clusters) {
    foreach ($vm in $vms) {

And to add to the execution time, you do another Get-VM with an object that is already the output from a Get-VM.

$ds = Get-VM $vm | Select-Object @{N = "Datastore"; E = { Get-Datastore -vm $_ } }


In $disks you seem to have SCSI Controller objects, not harddisks.
Also not sure what you are doing in the output with the Mode and Type properties?

If I have to guess what you are actually trying to do, I would use code like this.
 

$vc = Get-Content 'C:\temp\vSphere\vcs.txt'
$clusters = Get-Content 'C:\temp\vSphere\clusters.txt'

foreach ($v in $vc) {
    Connect-VIServer $v -Force
}

Get-Cluster -Name $clusters -PipelineVariable cluster |
Get-VM -PipelineVariable vm |
Get-HardDisk -PipelineVariable disk |
Get-ScsiControl -PipelineVariable scsi |
Where-Object {$_.BusSharingMode -in 'Physical','Virtual'} |
ForEach-Object -Process {
    New-Object -TypeName PSObject -Property ([ordered]@{
        ClusterName = $cluster.Name
        Name = $vm.Name
        VMHost = $vm.VMHost.Name
        Mode = $scsi.BusSharingMode
        Datastore = (Get-Datastore -RelatedObject $vm).Name -join '|'
    })
} | Export-Csv "C:\temp\Get-SCSIBusSharingVMs-Output.csv"


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

Reply
0 Kudos
PSScripter
Enthusiast
Enthusiast

First off, Thanks alot LucD for taking a look.

 

I do not think that first line is getting all vms for all vcs though.

 

PS C:\temp\vSphere\Storage> $clusters = Get-Content 'C:\temp\vSphere\clusters.txt'

PS C:\temp\vSphere\Storage> $vms = Get-Cluster $clusters | Get-VM -ErrorAction SilentlyContinue

PS C:\temp\vSphere\Storage> $vms.count
294

We do in fact have 294 machines in those 4 clusters in the cluster.txt list.

And those are the VMs I want to target. I am trying to determine which machines have SCSI bus sharing enabled and what mode.

 

When I run the version you posted, its only getting the info out of 1 of the clusters, its the 3rd cluster down from the top of the list in clusters.txt, but the data looks accurate for what its pulling.

As far as the mode and type, the mode looks good in the output, i was just trying to add a descriptive column that says 'Bus Sharing', so it reads, 'bus sharing' 'physical' etc.. in output.

 

Thanks!

 

Reply
0 Kudos
LucD
Leadership
Leadership

That depends what you have in the clsuters.txt file.
Is it the name of 1 cluster per line?


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

Reply
0 Kudos
LucD
Leadership
Leadership


We do in fact have 294 machines in those 4 clusters in the cluster.txt list.

And those are the VMs I want to target. I am trying to determine which machines have SCSI bus sharing enabled and what mode.

That is correct, but then you loop over all the clusters and use $vms as another loop (inside the clsuter loop).
So if you have 4 clusters, you are going to handles 4 * 294 VMs.


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

Reply
0 Kudos
PSScripter
Enthusiast
Enthusiast

yes, 4 clusters, 1 per line

Reply
0 Kudos
LucD
Leadership
Leadership

That is how my code expects it to be.
But it would amaze me if you only get the results of 1 out of the 4 clusters, unless you changed the code, like the location of the Export_Csv or the location of the Foreach-Object cmdlet.

I tested the code again and it works in my environment.


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

Reply
0 Kudos
PSScripter
Enthusiast
Enthusiast

I did not change anything, I ran again and get the same results but I see loads and loads of this message:

 

Get-ScsiController : 1/18/2023 9:50:21 AM Get-ScsiController The object 'vim.VirtualMachine:vm-32073' has already been deleted or has not been
completely created
At line:11 char:1
+ Get-ScsiController -PipelineVariable scsi |
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-ScsiController], ManagedObjectNotFound
+ FullyQualifiedErrorId : Client20_MoServiceImpl_GetViNetView_ViError,VMware.VimAutomation.ViCore.Cmdlets.Commands.VirtualDevice.GetScsiContro
ller

Get-ScsiController : 1/18/2023 9:50:21 AM Get-ScsiController The object 'vim.VirtualMachine:vm-32073' has already been deleted or has not been
completely created
At line:11 char:1
+ Get-ScsiController -PipelineVariable scsi |
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-ScsiController], ManagedObjectNotFound
+ FullyQualifiedErrorId : Client20_MoServiceImpl_GetViNetView_ViError,VMware.VimAutomation.ViCore.Cmdlets.Commands.VirtualDevice.GetScsiContro
ller

 

 

so I guess there is an object that is corrupt or something, and its preventing the rest of the output?

 

Edit - I actually changed the Get-Scsicontrol line to Get-ScsiController because it was barking about that.

Is there a way to exclude the vm-32073 and let it continue?

Reply
0 Kudos
PSScripter
Enthusiast
Enthusiast

I added -ErrorAction SilentlyContinue after the get-scsicontroller command, and am running again.

Reply
0 Kudos
LucD
Leadership
Leadership

You should try to stop/start your PS session.
That error sometimes happens when VM were deleted while your session was already open


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

Reply
0 Kudos
PSScripter
Enthusiast
Enthusiast

I tried a few times throughout the day, with new ps sessions, each time I get that error each time with a different vm name though.

I think if I just target each cluster individually and -append the csv, Ill get most of the data.

 

Any tips on how to add the DS Cluster name in there? I thought something like this would work, but not so much:

 

DatastoreCluster = (Get-DatastoreCluster -RelatedObject $cluster).Name -join '|'

 

Thanks!

 

Reply
0 Kudos
PSScripter
Enthusiast
Enthusiast

Boom:

$vc = Get-Content 'C:\temp\vSphere\vcs.txt'

foreach ($v in $vc) {
    Connect-VIServer $v -Force
}

Get-Cluster -Name 'clustername' -PipelineVariable cluster |
Get-VM -PipelineVariable vm |
Get-HardDisk -PipelineVariable disk |
Get-ScsiController -PipelineVariable scsi |
Where-Object {$_.BusSharingMode -in 'Physical','Virtual'} |
ForEach-Object -Process {
    $dsName = $disk.FileName.Split(']')[0].TrimStart('[')
    New-Object -TypeName PSObject -Property ([ordered]@{
        ClusterName = $cluster.Name
        Name = $vm.Name
        VMHost = $vm.VMHost.Name
        Mode = $scsi.BusSharingMode
        Datastore = (Get-Datastore -RelatedObject $vm).Name -join '|'
        DsCluster = (Get-DatastoreCluster -Datastore $dsName).Name
    })
} | Export-Csv -Append "C:\temp\Get-SCSIOutput.csv"

 

I have to run it 4 times to avoid that weird error, but it gets the job done.

Thanks!

Reply
0 Kudos
PSScripter
Enthusiast
Enthusiast

Here is my latest version, it takes quite awhile to run, around 44 minutes to go through 294 computers.

I never get those vm errors on this, and it goes through all the clusters, so I only need to run it 1 time:

 

    $vc = Get-Content 'C:\temp\vSphere\vcs.txt'
    $clusters = @{
        "VC1" = "Cluster1"
        "VC2" = "Cluster2"
        "VC3" = "Cluster3"
        "VC4" = "Cluster4"
    }
    foreach ($v in $vc) {
        Connect-VIServer $v -Force


        Get-Cluster -Name $clusters[$v] -PipelineVariable cluster |
        Get-VM -PipelineVariable vm |
        Get-HardDisk -PipelineVariable disk |
        Get-ScsiController -PipelineVariable scsi |
        Where-Object { $_.BusSharingMode -in 'Physical', 'Virtual' } |
        ForEach-Object -Process {
            $dsName = $disk.FileName.Split(']')[0].TrimStart('[')
            New-Object -TypeName PSObject -Property ([ordered]@{
                    ClusterName = $cluster.Name
                    Name        = $vm.Name
                    VMHost      = $vm.VMHost.Name
                    Mode        = $scsi.BusSharingMode
                    Datastore   = (Get-Datastore -RelatedObject $vm).Name -join '|'
                    DsCluster   = (Get-DatastoreCluster -Datastore $dsName).Name
                })
        }  | Export-Csv -Append "C:\temp\Output.csv"
        Disconnect-VIServer $v -Force -Confirm:$False
    }

 

 

Reply
0 Kudos