LittleNickey
Enthusiast
Enthusiast

Automating New-VM: Get-Datastore greater than X gb from csv-file.

Jump to solution

Hey all,

I recently bought the awesome book VMware vSphere PowerCLI Reference: Automating vSphere Administration and have been working on a modified script of the VM mass deployment.

I know it's not the most pretty code but it's a work in progress.

I have a csv-file, MassVMs.txt, with a "HardDisk" column and a "Cluster" column.

I want the script to take a random host in cluster X (from the csv-file) where the minimum avaliable disk is 1.1 times harddisk Y (from the csv-file).

Import-Csv .\MassVMs.txt|

     Foreach-Object {
          Get-Datastore -VMHost (get-cluster $_.Cluster|get-vmhost|get-random)|Where {($_.FreeSpaceMB * 1mb) -gt (($_.HardDisk * 1gb) * 1.1 )}
     }

The random host in Cluster X-part works great, $_.Cluster retrieves the specified cluster from the file.

Howerver $_.HardDisk doesn't as it seems, the scrip runs without errors and outputs all datastores in the cluster. If I replace "$_.HardDisk" with e.g. 100 it works as it should.

My conclusion is that maybe some command breaks the "connection" to the file? Or that I'm simply doing completely wrong. Anyone got any pointers?

-- Oskar
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership

Not if you have a blank after $row.HardDisk

You could try to change the order of the operands. Like this

($_.FreeSpaceMB * 1mb) -gt ((1GB * $row.HardDisk) * 1.5)}

Does that make any difference ?

And can you check what is actually in $row.HardDisk at the time of the error ?


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

View solution in original post

0 Kudos
9 Replies
LucD
Leadership
Leadership

Can you show us the CSV file you are using ?


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

0 Kudos
LittleNickey
Enthusiast
Enthusiast

It's pretty streight forward:

screen.PNG

I use in this example a very high number so the output ought to be null, but either way I enter "100" (gb, since that's what I've changed the script to) or go about using the same numbers (in KB) as the sample code from your book I still get the same output (all datastores).

Edited by: LittleNickey, added screenshot.

-- Oskar
0 Kudos
LucD
Leadership
Leadership

At the moment you reach the Where-clause the object in the pipeline is a datastore object (in the $_ variable).

The $_ variable does not contain a row from the CSV file anymore at that point.

You could do something like this

foreach($row in Import-Csv ./MassVMs.txt){
  Get-Datastore -VMHost (get-cluster $row.Cluster|get-vmhost|get-random)|
  Where {($_.FreeSpaceMB * 1mb) -gt (($row.HardDisk * 1gb) * 1.1 )}
}
 


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

LittleNickey
Enthusiast
Enthusiast

I must say that looks beautiful, but unfortunately it gives me an error:

The '*' operator failed: Exception of type 'System.OutOfMemoryException' was thrown..
At C:\script.ps1:7 char:53
+     Get-Datastore -VMHost (get-cluster $row.Cluster|get-vmhost|get-random)|?{
($_.FreeSpaceMB * 1mb) -gt (($row.HardDisk * <<<<  1gb) * 1.5)}
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : OperatorFailed
-- Oskar
0 Kudos
LucD
Leadership
Leadership

From the error message it looks that this is an out of memory exception.

Can you run the script for less clusters, or on a client with more memory ?


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

0 Kudos
LittleNickey
Enthusiast
Enthusiast

I'm only running the script on one cluster now during testing so that shouldn't be a issue.

I'm running this on my admin VM so I upgraded from 2GB -> 8GB memory but it still gives me the same error. I also ran the script from the vCenter server.

Am I wrong when I interpret the error message; that the asterix (*) is read by powerCLI as a wildcard instead of a multiplication?

-- Oskar
0 Kudos
LucD
Leadership
Leadership

Not if you have a blank after $row.HardDisk

You could try to change the order of the operands. Like this

($_.FreeSpaceMB * 1mb) -gt ((1GB * $row.HardDisk) * 1.5)}

Does that make any difference ?

And can you check what is actually in $row.HardDisk at the time of the error ?


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

0 Kudos
LittleNickey
Enthusiast
Enthusiast

Huh.. That actually worked! Bug?

Here is the finished product (or well, finished part of the product):

foreach($row in Import-Csv .\MassVMs.txt){
     Get-Datastore -VMHost (get-cluster $row.Cluster|get-vmhost|get-random)|
     ?{($_.FreeSpaceMB * 1mb) -gt ((1GB * $row.HardDisk) * 1.5)}|sort FreeSpaceGB|ft -auto
}
-- Oskar
0 Kudos
LucD
Leadership
Leadership

No bug, type casting.

WHat happens is the following:

  • an Import-Csv produces all properties as [string]
  • the operator multiply (*) is encounterd
  • PS looks at the operands left to right to determine what kind of operation needs to be performed
  • it see that the left operand is a string and doesn't know what to do

By changing the order, PS sees an [int] on the left side and will do a [int] cast on the right operand.

You could have kept the order and do the cast in the script

[int]$row.HardDisk

But I would have expected a more meaningful message, not an out of memory exception :smileygrin:


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