VMware Cloud Community
nicolestroff
Contributor
Contributor
Jump to solution

Sanity Check, ESXi

Hey Guy's ... Smiley Happy

Maybe one of you can help me.

I need the option, best a function like a "sanity check", which reviewed the Datastore and all other Resources (RAM, CPU, ..) before i install a vrtual machine via a powershell script.

I would like to receive a message, if the installation of >number of VMs< is possible or not - If yes, the function should exit and the installation process from the VMs should start.

What i want to avoid is, that i entry all the necessary informations (how much RAM, how many CPU, which Datastore, ...) and after it, the skript breaks up because there is not enough diskspace or else.

### At the Point "check H/W Rescources" i don't want this output, i only want a response like "you have enough resource, let's create some VMs" or else .. ###

This is my script:

$HyperVisor = Read-Host 'Please type the Name or IP of the Hypervisor'

$vUSERNAME = Read-Host 'Please type the Name from the User'

$vPassword = Read-Host 'Please type the Password' -AsSecureString

$vcredential = New-Object System.Management.Automation.PSCredential ($vusername, $vPassword)

$ServerOSGuestID = "Windows9Server64Guest"

$ClientOSGuestID = "Windows9_64Guest"

$DatastoreSSD = "SSD Datastore"

$DatastoreHDD = "HDD Datastore"

$ISOPathServerOS = "[OS Partition] Win2016/Windows_Server_2016_STD.iso"

$ISOPathClientOS = "[OS Partition] Win10/en_windows_10_multiple_editions_version_1607_updated_jul_2016_x64_dvd_9058187.iso"

$IsoXmlServer = "[OS Partition] Win2016/XML_WIN2k16_Feb2018_U3.iso"

$IsoXmlClient = "[OS Partition] Win10/XML_Win10_Feb2018.iso"

############################

#   Connection Hypervisor  #

############################

Write-Host "Connecting to $HyperVisor..." -Foregroundcolor "Yellow" -NoNewLine

$connection = Connect-VIServer -Server $HyperVisor -Cred $vcredential -ErrorAction SilentlyContinue -WarningAction 0 | Out-Null

If($? -Eq $True)

{

    Write-Host "Connected" -Foregroundcolor "Green"

}

Else

{

    Write-Host "Error in Connecting to $HyperVisor; Try Again with correct user name & password!" -Foregroundcolor "Red"; exit;

}

##########################

#   Check HW Ressource   #

##########################

Write-Host "*******************************************************************************"

Write-Host -ForegroundColor Green "Please let me check the Hardware-Ressource for you"

Write-Host "*******************************************************************************"

Write-Host ""

sleep 3

Write-Host "Colleacting Datastore report....." -f yellow

#Get-Datastore | select Name, @{N="Capacity(GB)";E={[Math]::Round($_.CapacityMB/1024,2)}}, @{N="FreeSpace(GB)";E={[Math]::Round($_.FreeSpaceMB/1024,2)}}, @{N="Free Space (%)";E={[math]::Round(((100* ($_.FreeSpaceMB))/ ($_.CapacityMB)),0)}} | sort -Property "Free Space (%)"

Get-Datastore

#Write-Host "I'm ready. Here is a List with all your Datastores" -f green

####################### output separat deklarieren ################

$Continue = Read-Host "Do you want to continue? [Y] Yes [N] No [A] Abort"

switch($Continue) {

Y {Write-Host "Ok. Let's create some VM/VMs" -f cyan; ($Continue -eq $True); break}

N {Write-Host "Maybe there's not enough space on the Datastore. You should expand it" -f Red; exit}

A {Write-Host "Why are you so irresolute?" -f Yellow; exit}

default {Write-Host "Possibly you should drink a cup of coffee and try it, in a few minutes, again.." -f DarkYellow; exit}

}

##################

#   Run Skript   #

##################

$VM_prefix = Read-Host "Typ the name of the VM/VMs"

Write-Host "Your VM/VMs named $VM_prefix" -foreground green

$vm_count =Read-Host "How many virtual machines do you want to create?"

switch -regex ($vm_count)

{

    [1-10] {Write-Host "You want to create $vm_count VM/VMs" -foreground green; break}

    default {Write-Host "You can't create more than ten virtual machines." -foreground red}

}

$Guest = Read-Host "Choose your prefered GuestOS [S] Server or [C] Client"

switch($Guest)

{

Server {Write-Host "You choose Server as the Guest-ID" -foreground green; $GuestOS=$ServerOSGuestID; break}

Client {Write-Host "You choose Client as the Guest-ID" -foreground green; $GuestOS=$ClientOSGuestID; break}

default {Write-Host "This is not an option" -foreground red; return}

}

$VCPU = Read-Host "How many CPU do you want to use"

switch -regex ($VCPU)

{

    [1-10] {Write-Host "Your VM/VMs should have $VCPU CPUs" -foreground green; break}

    default {Write-Host "This is not an option" -foreground red}

}

$VRAM = Read-Host "How many RAM do you want to use?"

Write-Host "Your VM/VMs now has $VRAM RAM" -foreground green

$VDisk = Read-Host "How many Diskspace do you prefered?"

Write-Host "Your VM/VMs now has $VDisk Diskspace" -foreground green

$Datastore = Read-Host "Which Datastore should contains your VM/VMs? [S] SSD Datastore or [H] HDD Datastore"

$Path = Read-Host "Type the ISO Path from your OS (Server or Client)"

switch($Datastore)

{

S {Write-Host "You choose SSD Datastore as your Datastore" -foreground Cyan; $DataPool=$DatastoreSSD; break}

H {Write-Host "You choose HDD Datastore as your Datastore" -foreground Cyan; $DataPool=$DatastoreHDD; break}

}

switch($Path)

{

Server {Write-Host "You choose the OS-ISO as the Server OS " -foreground Cyan; $DataPath=$ISOPathServerOS; break}

Client {Write-Host "You choose the OS-ISO as the Client OS" -foreground Cyan; $DataPath=$ISOPathClientOS; break}

}

1..$vm_count | foreach {

$y="{0:00}" -f $_

$VM_name= $VM_prefix + $y

New-VM -Name $VM_name -VMHost $VMH -GuestID $GuestOS -NumCPU $VCPU -MemoryGB $VRAM -DiskGB $VDisk -Datastore $DataPool -CD

write-host "Power On of the  VM $VM_name initiated"  -foreground green

Get-VM $VM_name | Get-CDDrive | Set-CDDrive -ISOPath $DataPath -StartConnected:$true -Confirm:$false

if ($DataPath -eq $ServerPath1) {

New-CDDrive -VM $VM_name -ISOPath $IsoXmlServer -StartConnected -Confirm:$false

}

else {

New-CDDrive -VM $VM_name -ISOPath $IsoXmlClient -StartConnected -Confirm:$false

}

Start-VM -VM $VM_name -confirm:$false -RunAsync

}

return

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

The following should be a bare minimum skeleton script.

It uses a CSV file to provide the input. The layout of the CSV is described in the comments at the top.

The script allows for overcommits (see the $cpuMax, $memoryMax and $datastoreMax variables).

The testing for sufficient resources takes these overcommit values into account, but you will most probably have to adjust them for your environment.

For example, if all your VMs are configured with 4GB of memory, but they only use 50% on average, you can probably set the $memoryMax value to 2.

On the New-VM cmdlet I used the splatting technique to make the code a bit more readable.

I also kept the output on screen to a minimum, you can add output at any point as you like.

And yes, I know that hard-coding passwords is not a best practice, but there are solutions available to not store these passwords in the CSV file.

You could for example look at the New-VICredentialStoreItem.

I hope this skeleton helps in setting you on your way :smileygrin:

# Input - CSV file

#

# Layout

# VMHost,User,Password,VMname,guestOS,Datastore,HarddiskGB,vCPU,MemoryGB,OSISO,XmlISO

# esx1,root,"VMware1!",vm1,Windows9Server64Guest,"HDD Datastore",40,2,4,"[OS Partition] Win2016/Windows_Server_2016_STD.iso","[OS Partition] Win2016/XML_WIN2k16_Feb2018_U3.iso"

# esx1,root,"VMware1!",vm2,Windows9_64Guest,"SSD Datastore",60,4,8,"[OS Partition] Win10/en_windows_10_multiple_editions_version_1607_updated_jul_2016_x64_dvd_9058187.iso","[OS Partition] Win10/XML_Win10_Feb2018.iso"

#

# Resource maximums

# Value -gt 1 means an overcommit

$cpuMax = 1.75

$memoryMax = 1.50

$datastoreMax = 1

Import-Csv -Path .\input.csv -UseCulture | %{

    # Connect to ESXi

   

    Connect-VIServer -Server $_.VMHost -User $_.User -Password $_.Password | Out-Null

    # Check resources

    $esx = Get-VMHost -Name $_.VMHost

    # Storage

    $dsOK = $false

    $ds = Get-Datastore -Name $_.Datastore

    if((($ds.FreeSpaceGB * $datastoreMax) -gt $_.HardDiskGB){

        $dsOK = $true

    }

    # CPU

    $cpuOK = $false

    $vmCpu = Get-VM -Location $esx | Measure-Object -Property NumCpu -Sum | Select -ExpandProperty Sum

    if((($esx.NumCpu * $cpuMax) - $vmCpu) -gt $_.vCPU){

        $cpuOK = $true

    }

    # Memory

    $memOK = $false

    $vmMem = Get-VM -Location $esx | Measure-Object -Property MemoryGB -Sum | Select -ExpandProperty Sum

    if((($esx.MemoryTotalGB * $memMax) - $vmMem) -gt $_.MemoryGB){

        $memOK = $true

    }

    if($dsOK -and $cpuOK -and $memOK){

        # Create the VM

   

        $sNew = @{

            Name = $_.VMName

            VMHost = $_.VMHost

            GuestID = $_.guestOS

            NumCpu = $_.vCPU

            MemoryGB = $_.MemoryGB

            DiskGB = $_.HarddiskGB

            Datastore = $_.Datastore

        }

        $vm = New-VM @sNew

        Get-CDDrive -VM $vm | Set-CDDrive -ISOPath $_.OSISO -StartConnected:$true -Confirm:$false

   

        New-CDDrive -VM $vm -ISOPath $$_.XmlISO -StartConnected -Confirm:$false

   

        Start-VM -VM $vm -Confirm:$false -RunAsync

        Write-Host "VM $($_.VMname) created and started"

    }

    else{

        Write-Host "Not sufficient resources for $($_.VMname) - Memory = $memOK/CPU $cpuOK/Storage $dsOK"

    }

    # Clean up

   

    Disconnect-VIServer -Server $_.VMHost -Confirm:$false

}


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

View solution in original post

15 Replies
LucD
Leadership
Leadership
Jump to solution

These is for deployment on stand-alone ESXi nodes, correct?

So there is no vCenter functionality available.

To check if there are enough resources available, the script should know what is required to deploy a VM.

Where do you get those values (vCPU, mem, disk storage...)?

Will they be hard-coded, or entered when you run the script?


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

Reply
0 Kudos
nicolestroff
Contributor
Contributor
Jump to solution

Dear LucD,

yes, at the moment it's a stand alone esxi.

Later, it should be a member of a vCenter.

The values should not be hard-coded.

The "user" (Admin or whoever) answer questions (read-host) which contains in variables.

The resources should be queried on the basis of these variables.

Like .....

"

$VM_prefix = Read-Host "Typ the name of the VM/VMs"

Write-Host "Your VM/VMs named $VM_prefix" -foreground green

$vm_count =Read-Host "How many virtual machines do you want to create?"

switch -regex ($vm_count)

{

    [1-10] {Write-Host "You want to create $vm_count VM/VMs" -foreground green; break}

    default {Write-Host "You can't create more than ten virtual machines." -foreground red}

}

$Guest = Read-Host "Choose your prefered GuestOS [S] Server or [C] Client"

switch($Guest)

{

Server {Write-Host "You choose Server as the Guest-ID" -foreground green; $GuestOS=$ServerOSGuestID; break}

Client {Write-Host "You choose Client as the Guest-ID" -foreground green; $GuestOS=$ClientOSGuestID; break}

default {Write-Host "This is not an option" -foreground red; return}

}

$VCPU = Read-Host "How many CPU do you want to use"

switch -regex ($VCPU)

{

    [1-10] {Write-Host "Your VM/VMs should have $VCPU CPUs" -foreground green; break}

    default {Write-Host "This is not an option" -foreground red}

}

$VRAM = Read-Host "How many RAM do you want to use?"

Write-Host "Your VM/VMs now has $VRAM RAM" -foreground green

$VDisk = Read-Host "How many Diskspace do you prefered?"

Write-Host "Your VM/VMs now has $VDisk Diskspace" -foreground green

$Datastore = Read-Host "Which Datastore should contains your VM/VMs? [S] SSD Datastore or [H] HDD Datastore"

$Path = Read-Host "Type the ISO Path from your OS (Server or Client)"

switch($Datastore)

{

S {Write-Host "You choose SSD Datastore as your Datastore" -foreground Cyan; $DataPool=$DatastoreSSD; break}

H {Write-Host "You choose HDD Datastore as your Datastore" -foreground Cyan; $DataPool=$DatastoreHDD; break}

}

switch($Path)

{

Server {Write-Host "You choose the OS-ISO as the Server OS " -foreground Cyan; $DataPath=$ISOPathServerOS; break}

Client {Write-Host "You choose the OS-ISO as the Client OS" -foreground Cyan; $DataPath=$ISOPathClientOS; break}

}

"

After this entrys, it should check the resources and should response a yes or a no ..

Lg

*sorry, but i'm a little esxi/powercli noob and i'm still learning. :smileygrin:

Reply
0 Kudos
nicolestroff
Contributor
Contributor
Jump to solution

lf there is also an easier way to check this without having to type everything in order to finally get an error due to lack of RAM .. please !

Let me know .. Smiley Happy

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I would opt for an input file with the requests, that would allow you to run the script in the background and it would allow you to keep track of what was created.

And eventually even reuse a fle.


You could then decide if the script only goes ahead if there are sufficient resources free for all requested VMs in the file, or the script could start creating VMs, till there are not enough resources anymore.

On the available resources, you will also need to decide if you will permit overcommitment or not.

If you allow overcommitment, you would need to define how much can be overcommitted. For example, memory with 25%, vCPU with 10%...


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

nicolestroff
Contributor
Contributor
Jump to solution

Dear LucD

this would be a very nice solution. Thanks !

I hope i can do this. haha*  It will be a challenge in any case .. ^^

But please, can you explain "fle". Or is it only a spelling mistake ?

Maybe you can also give me a little hint how I can start this "project" in a best practice ?

Lg, Nicole

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That should have said "file" :smileygrin:

Sure, there are a number of steps (that in fact come back in many scripts one writes).

  1. Define how your input will look
    1. Interactive or not? In this case I would go for file-based (see above)
    2. If in a file, which file format (CSV, JSON, XML....)? Pick whatever you are most comfortable with
  2. Define you constants. In other words, how would you determine what "sufficient" resources are?
  3. Write a skeleton script, that handles the main parts of the logic you have in mind
    1. Read the input
    2. Check if conditions are met
    3. Take action (create VM)
    4. Inform what happened (on screen, or via an output file)
  4. Refine you script
    1. Handle errors
    2. Handle exceptions

I'll try to come up with a sample skeleton script, hold on.


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

nicolestroff
Contributor
Contributor
Jump to solution

Wow .. thats very nice from you !

Thanks for your help ... :smileygrin:

I'm looking forward to the skeleton script Smiley Happy

Lg, Nicole

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The following should be a bare minimum skeleton script.

It uses a CSV file to provide the input. The layout of the CSV is described in the comments at the top.

The script allows for overcommits (see the $cpuMax, $memoryMax and $datastoreMax variables).

The testing for sufficient resources takes these overcommit values into account, but you will most probably have to adjust them for your environment.

For example, if all your VMs are configured with 4GB of memory, but they only use 50% on average, you can probably set the $memoryMax value to 2.

On the New-VM cmdlet I used the splatting technique to make the code a bit more readable.

I also kept the output on screen to a minimum, you can add output at any point as you like.

And yes, I know that hard-coding passwords is not a best practice, but there are solutions available to not store these passwords in the CSV file.

You could for example look at the New-VICredentialStoreItem.

I hope this skeleton helps in setting you on your way :smileygrin:

# Input - CSV file

#

# Layout

# VMHost,User,Password,VMname,guestOS,Datastore,HarddiskGB,vCPU,MemoryGB,OSISO,XmlISO

# esx1,root,"VMware1!",vm1,Windows9Server64Guest,"HDD Datastore",40,2,4,"[OS Partition] Win2016/Windows_Server_2016_STD.iso","[OS Partition] Win2016/XML_WIN2k16_Feb2018_U3.iso"

# esx1,root,"VMware1!",vm2,Windows9_64Guest,"SSD Datastore",60,4,8,"[OS Partition] Win10/en_windows_10_multiple_editions_version_1607_updated_jul_2016_x64_dvd_9058187.iso","[OS Partition] Win10/XML_Win10_Feb2018.iso"

#

# Resource maximums

# Value -gt 1 means an overcommit

$cpuMax = 1.75

$memoryMax = 1.50

$datastoreMax = 1

Import-Csv -Path .\input.csv -UseCulture | %{

    # Connect to ESXi

   

    Connect-VIServer -Server $_.VMHost -User $_.User -Password $_.Password | Out-Null

    # Check resources

    $esx = Get-VMHost -Name $_.VMHost

    # Storage

    $dsOK = $false

    $ds = Get-Datastore -Name $_.Datastore

    if((($ds.FreeSpaceGB * $datastoreMax) -gt $_.HardDiskGB){

        $dsOK = $true

    }

    # CPU

    $cpuOK = $false

    $vmCpu = Get-VM -Location $esx | Measure-Object -Property NumCpu -Sum | Select -ExpandProperty Sum

    if((($esx.NumCpu * $cpuMax) - $vmCpu) -gt $_.vCPU){

        $cpuOK = $true

    }

    # Memory

    $memOK = $false

    $vmMem = Get-VM -Location $esx | Measure-Object -Property MemoryGB -Sum | Select -ExpandProperty Sum

    if((($esx.MemoryTotalGB * $memMax) - $vmMem) -gt $_.MemoryGB){

        $memOK = $true

    }

    if($dsOK -and $cpuOK -and $memOK){

        # Create the VM

   

        $sNew = @{

            Name = $_.VMName

            VMHost = $_.VMHost

            GuestID = $_.guestOS

            NumCpu = $_.vCPU

            MemoryGB = $_.MemoryGB

            DiskGB = $_.HarddiskGB

            Datastore = $_.Datastore

        }

        $vm = New-VM @sNew

        Get-CDDrive -VM $vm | Set-CDDrive -ISOPath $_.OSISO -StartConnected:$true -Confirm:$false

   

        New-CDDrive -VM $vm -ISOPath $$_.XmlISO -StartConnected -Confirm:$false

   

        Start-VM -VM $vm -Confirm:$false -RunAsync

        Write-Host "VM $($_.VMname) created and started"

    }

    else{

        Write-Host "Not sufficient resources for $($_.VMname) - Memory = $memOK/CPU $cpuOK/Storage $dsOK"

    }

    # Clean up

   

    Disconnect-VIServer -Server $_.VMHost -Confirm:$false

}


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

LucD
Leadership
Leadership
Jump to solution

To avoid copy/paste issues, I attach the script.


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

Reply
0 Kudos
nicolestroff
Contributor
Contributor
Jump to solution

That's really helpful!

Thank you so much for taking the time to do this :smileyblush: Smiley Happy

Reply
0 Kudos
nicolestroff
Contributor
Contributor
Jump to solution

Hello LucD,

I'm sorry, but maybe you can help me one more.

Here's my function:

$VDisk = Read-Host "How many Diskspace (GB) do you prefered?"

Write-Host "Your VM/VMs now has $VDisk GB Diskspace" -foreground green

$datastoreA = Get-Datastore -Name "SSD Datastore"

function HVResource ($datastoreA) {

if ($VDisk -le $datastoreA) {

    "Es ist genügen Platz. Leg los !"

}

Elseif ($VDisk -ge $datastoreA) {

    "Das glaub ich nicht, Tim."

}

    }

HVResource

****************************

Now, it doesn't matter which value I'm enter as the "$VDisk" variable.

The return value is always "Das glaub ich nicht, Tim."  But why ?

If i tried another option, like .. "if ($VDisk.FreeSpaceGB -le $datastoreA.FreeSpaceGB)" everytime the return code is "Es ist genügen Platz. Leg los !"

Where is my problem ?

Best Regards,

Nicole

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Your issue comes from the values you are using in the variables.

The $VDisk variable contains a number, it is a scalar, so no FreeSpaceGb property on there.

The $datastoreA variable contains a Datastore object (output from Get-Datastore), and those do have a FreeSpaceGB property.

It is also a good practice to define the variables you are passing to a function explicitly as parameters, and not rely on scope.

Packing all that together, you could do something like this

function HVResource ($dsName,$DiskGB) {

   

    $ds = Get-Datastore -Name $dsName

    if ($vdkGB -le $ds.FreeSpaceGB) {

        "Es ist genügen Platz. Leg los !"

    }

    Else{

        "Das glaub ich nicht, Tim."

    }

}

$VDisk = Read-Host "How mmuch Diskspace (GB) do you prefer?"

Write-Host "Your VM/VMs wants $VDisk GB Diskspace" -foreground green

HVResource -dsName "SSD Datastore" -DiskGB $VDisk


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

Reply
0 Kudos
nicolestroff
Contributor
Contributor
Jump to solution

Hello Smiley Happy

How can I convert the value of $VDisk into a datastore object with "FreeSpaceGB properties ?

You also wrote "if ($vdkGB -le $ds.FreeSpaceGB)" - which value conatins "$vdkGB" and how did you define that ?

Best Regards and thanks for your help Smiley Happy

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can't, the $VDisk variable contains a number (the number of GB the user wants to assign).

The $vdkGB is a typo, that should have said $DiskGB, which is one of the parameters passed to the HVResource function.

This is the corrected code.

function HVResource ($dsName,$DiskGB) {

  

    $ds = Get-Datastore -Name $dsName

    if ($DiskGB -le $ds.FreeSpaceGB) {

        "Es ist genügen Platz. Leg los !"

    }

    Else{

        "Das glaub ich nicht, Tim."

    }

}

$VDisk = Read-Host "How mmuch Diskspace (GB) do you prefer?"

Write-Host "Your VM/VMs wants $VDisk GB Diskspace" -foreground green

HVResource -dsName "SSD Datastore" -DiskGB $VDisk

 


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

Reply
0 Kudos
nicolestroff
Contributor
Contributor
Jump to solution

.. damned. if you think you get it and then it is not ! -.-
It is not so easy to understand PS and PCli in order to work properly.

so thank you for your help ! Smiley Happy

Lg, Nicole

Reply
0 Kudos