Hey Guy's ... ![]()
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
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
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
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:
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 .. ![]()
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
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
That should have said "file" :smileygrin:
Sure, there are a number of steps (that in fact come back in many scripts one writes).
I'll try to come up with a sample skeleton script, hold on.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Wow .. thats very nice from you !
Thanks for your help ... :smileygrin:
I'm looking forward to the skeleton script ![]()
Lg, Nicole
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
To avoid copy/paste issues, I attach the script.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
That's really helpful!
Thank you so much for taking the time to do this :smileyblush: ![]()
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
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
Hello ![]()
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 ![]()
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
.. 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 ! ![]()
Lg, Nicole
