PowerShell function for menu creation revisited

Sometimes when creating blog posts you just get excited to publish a post as soon as it’s finished, but then you realize you can do something better. So yesterday I published a post on how to use a function in PowerShell to create an interactive dynamic menu but in hindsight it could have been more “generic” – so today I’m back with a new post on how you can create that generic function by providing the query in a separate string instead as part of the function itself. This allows you to merely change the query (the input for creating the menu) without having to change anything inside the function. Now it’s a “real” function! 🙂

I’ve added two mandatory parameters to the function, the first is the query to retrieve data and the second parameter is the task that you’d like to perform on the selected object. I’m calling the parameters -ListItem and -GetItem but the actual query is set in the $MyQuery and $MyTask string and they are then passed on to the function to perform the task. So if I’d like to get a list of VMs I just change the $MyQuery to something like “(Get-VM | Sort-Object)” and if I’d like to get a list of Datastores I set $MyQuery = “(Get-Datastore | Where {$_.Type -eq ‘VMFS’} | Sort-Object -Descending FreeSpaceGB)”. Once the list is presented and you select an object you then pass on what’s going to happen with it with the $MyTask – so if I want to retrieve a specific VM I set it to “Get-VM” but it could be anything (like Remove-VM but there’s no warning so be careful!)

Get a list of VMs
Get a list of VMFS datastores and sort them based on free space

Calling the function is then done using this syntax:
Set-Menu -ListItem $MyQuery -GetItem $MyTask

$VIServer = "vcsa.mydomain.com"
$VIUsername = "administrator@vsphere.local"
$VIPassword = "MyPassword"

Connect-VIServer $VIServer -User $VIUsername -Password $VIPassword -WarningAction SilentlyContinue

$MyQuery = (Get-Datastore | Where {$_.Type -eq 'VMFS'} |Sort-Object -Descending FreeSpaceGB)
$MyTask = "Get-Datastore"

Function Set-Menu {
    Param (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        $ListItem,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        $GetItem
    )

    Try {
    $menu = @{}
    For ($i=1;$i -le $ListItem.count; $i++)
        { Write-Host "$i. $($ListItem[$i-1].Name)"
        $menu.Add($i,($ListItem[$i-1].Name)) }
    [int]$ans = if(($ans = Read-Host "Select item or press enter to accept default value [1]") -eq '') {"1"} else {$ans}
    $Selection = $menu.Item($ans); Invoke-Expression $($GetItem +  " " + $Selection)
    }

    Catch {
    Write-Host "The selection you made is unavailable, please make a valid selection between 1 and $($i-1)..."
    }
}

cls

Set-Menu -ListItem $MyQuery -GetItem $MyTask

Disconnect-VIServer $VIServer -Confirm:$false
Set-Menu waiting for user input
Set-Menu has executed the task defined in $MyTask

The way you can use the function is up to you but I use it in William Lams vghetto-vsphere-automated-lab-deployment script

Simplify your life with dynamic menus in PowerShell

If you are anything like me you’re setting up test or demo environments and then tearing them down a few hours later when you’re done with what ever testing you were doing. While setting up a VMware vSphere test environment is super easy using powershell/powercli (if you haven’t already visited William Lams web page, I highly recommend it and while you’re there grab the PowerShell scripts to deploy vSphere/vSAN/NSX environments. Kudos to William for everything you do for the vCommunity!!), I use his powershell scripts almost on a daily basis!

Now while setting up a single lab environment is usually not a big problem using the scripts provided by Willam but when you start setting up multiple labs (I typically have like 3 or 4 labs set up on any given time for different purposes) you might run out of some resources statically configured in the script, for instance your datastore configured doesn’t have enough capacity. So why not enhance the experience with dynamic selection of for instance datastore (or in my example: DatastoreCluster). Turns out it’s really easy to build an interactive dynamic menu of your datastoresclusters and use the menu to select where to install the lab environment.

I’m using a function to call the datastoreclusters I can use. I have a basic error handling included that you might need to extend. The code below includes 2 examples, the first function is calling available DatastoreClusters from a vCenter server and ordering them based on available free space and the second example gets a list of port groups available on my distributed switch. I’ve also assigned a default selection/value for faster deployments, just press enter to select the default value.

$VIServer = "vcsa.mydomain.com"
$VIUsername = "administrator@vsphere.local"
$VIPassword = "MyPassword"

Connect-VIServer $VIServer -User $VIUsername -Password $VIPassword -WarningAction SilentlyContinue

Function Show-DatastoreClusters ($Title = 'My Datastores'){
Try {
$AvailDatastores = (Get-Datastore | Where {$_.Type -eq "VMFS"} |Sort-Object -Descending FreeSpaceGB)
$menuds = @{}
For ($i=1;$i -le $AvailDatastores.count; $i++)
{ Write-Host "$i. $($AvailDatastores[$i-1].Name) - $([math]::Round($AvailDatastores[$i-1].FreespaceGB,1)) GB free space"
$menuds.Add($i,($AvailDatastores[$i-1].Name)) }
[int]$ansds = if(($ansds = Read-Host "Select Datastore or press enter to accept default value [1]") -eq ''){"1"} else {$ansds}
$DatastoreSelection = $menuds.Item($ansds) ; Get-Datastore $DatastoreSelection
}
Catch { Write-Host "The selection you made is unavailable, please make a valid selection between 1 and $($i-1)..." Start-Sleep 2 }
}

Function Show-PortGroups ($Title = 'My Portgroups'){
Try {
$AvailPortgroups = (Get-VDSwitch -Name "DSwitch" | Get-VDPortgroup)
$menupg = @{}
For ($i=1;$i -le $AvailPortgroups.count; $i++)
{ Write-Host "$i. $($AvailPortgroups[$i-1].Name)"
$menupg.Add($i,($AvailPortgroups[$i-1].Name)) }
[int]$anspg = if(($anspg = Read-Host "Select portgroup or press enter to accept default value [7]") -eq ''){"7"}else{$anspg}
$PortgroupSelection = $menupg.Item($anspg) ; Get-VDPortgroup $PortgroupSelection
}
Catch { Write-Host "The selection you made is unavailable, please make a valid selection between 1 and $($i-1)..." Start-Sleep 2 }
}
cls
Write-Host `n
$VMDatastore = Show-DatastoreClusters
Write-Host `n
$VMNetwork = Show-Portgroups
Write-Host `n
$VMDatastore
$VMNetwork

Disconnect-VIServer $VIServer -Confirm:$false

The function above can then be included in the script from William Lam. When calling the function the output will look something like this (the menus being produced are highlighted in red):

Function to build dynamic menu

If you’d like you can add some extra granularity when enumerating the datastore, expand the “Where” statement to just get the datastores with a specific name:

{$_.Type -eq "VMFS" -and $_.Name -like "VMFS-ESXi7*"}

Once you got you script fetching the desired data you can add the function to any script, I’ve added it to William’s script for some added flexibility.

How to setup Veeam replication with VMware vCloud Director

Veeam Backup & Replication 9.5 update 4 has now finally been released (to the VCSP community first and the general public on the 22:nd of January). There are loads of really interesting updates and new features.

Veeam Backup & Replication 9.5 update 4

To name a few of the enhancement/new features:

  • Capacity tier: Support for object based storage, gives you access to BLOB storage from Microsoft Azure, Amazon S3 and S3 compatible as well as IBM Cloud Object Storage. This is a new addition to Scale-Out backup repository users. You have your local “performance tier” as per usual but you can offload data based on age or space to object based storage.
  • Staged restore (GDPR compliance for instance, the right to be forgotten  or other use cases where you’d need to run a script on the VM before restoring it)
  • Secure restore where you can do a virus scan on the VM before restoring
  • Direct restore to Amazon EC2 – restoring to Azure has been available for a while but now you can also choose to restore your on-premises infrastructure VMs to Amazon EC2 – combined with the functionality of the backup vendor Veeam acquired a year ago called N2WS for backing up EC2 instances we now have a whole other level of portability of our data: backup everything, restore where it makes the most sense.
  • Self-service backup and restore portal using Enterprise manager
  • Enhancements to various Veeam explorers
  • Plugins for SAP HANA and Oracle RMAN
  • Platform support: vSphere 6.7 update 1, Windows Server 2019 and vCloud Director 9.5

But going back to the fact that update 4 now is available for VCSPs (or Veeam Cloud & Service Provider), there have been some updates for VMware environments as well (VMware calls their service provider program “VCPP”). Included in the VCPP program is a great product called vCloud Director that has been around for ages but is only available for service providers to use nowadays. VMware vCloud Director is an abstraction layer on top of vCenter so up until now there has been no support for vCloud Director for Veeam Cloud Connect usage when replicating VMs from a customer to the service provider environment. The solution previously was to replicate VMs to the service provider vCenter using Cloud Connect and then manually import VMs to the correct organization from vCloud Director. With update 4 that manual step has now been removed, and the process has in fact been improved since the customer can – using cloud connect and a single port mind you! (no VPN required) – replicate virtual machines from the onsite vSphere environment directly to their own Organization and Org vDC. The customer can also set up failover plans and run those if needed all using the same vCloud Director credentials they already received from the service provider.

It’s really easy to setup, below is a video where I show you how to configure the service provider bits such as adding vCloud Director, setting up tenants but also how the customer would configure their environment i.e. how to connect to a service provider using Cloud Connect and setting up replication jobs from a local environment and replicating VMs to the service provider vCloud Director and the customers org vDC within that environment.

(The video is in swedish but just turn off the sound if you don’t understand)