Category Archives: Coding

VMware VMRC Console Links with PowerCLI Core on macOS and Linux

I got thinking the other day about how much I hate logging into vSphere Web Client/vSphere Client. In a large environment with different SSO domains, you end up wasting 10 mins logging in. So, thinking about work while trying to sleep, I made a note to look into launching VMRC from PowerCLI Core on my Mac.

Being a Mac user, I will pretty much do anything in my power not to have to jump to a windows box, and as it turns out, the Open-VMConsoleWindow cmdlet is not supported within PowerShelll Core.

Not supported on PowerShell Core
Not supported on PowerShell Core

Yes, I could jump to another machine, but seriously, that is a pain, so I did a search thinking’s Python might be the only way also, would be helpful as I need to knuckle down and up my game on the Python front. I have a hard time creating anything in Python when there is no real requirement, apart from skilling up ….

Understand

To start the process, I did a Google search and came across an article by Roman Dodin, unfortunately, his post is no longer available. The VMRC link looks something like:-

vmrc://ezra@lab.local@vc01.lab.local:443/?moid=vm-320 (vCenter)

vmrc://ezra@lab.local@esx01.lab.local:443/?moid=320 (ESXi)

Link construction is made up of the following:-

  • user or user@domain
  • vCenter/ESXi IP or FQDN
  • Virtual Machine MoRef ID

With that info, what I thought was going to be more complex ended up being super easy, you can craft the URL yourself and use PowerShell.

Design

So recently, I have been building up a “Toolkit” which essentially is a PowerShell module with many cmdlets to make my day to day tasks a whole lot easier, and this function will fit perfectly.

As I have made the function to go into my Toolkit module, there are a couple of things to bear in mind.

  • My credentials are stored in a variable called $Creds
  • A connection is already established with a ESXi Host or vCenter server.

To keep things nice a simple, I had two requirements for the function:-

  1. Must accept pipeline input
    Get-VM test01 | Open-VMRC
  2. Must accept VM name parameter
    Open-VMRC test01

With the knowledge of the link construction I will use following variables:-

$vm = “test01”                  # VM Name
$vmID = 320                     # MoRef ID
$vcsa = “vc01.lab.local”        # vCenter or ESXi Host
$creds = Get-Credentials        # Credentials for access 
$url =                          # Crafted URL depending on target

Steps

To get things started, I needed to find a way to launch the URL. I’m sure there are a few ways to tackle this, I choose to use theStart-Process cmdlet.

Start-Process -Path "vmrc://ezra@lab.local@esx01.lab.local:443/?moid=320"

To meet the pipeline requirement, we can enable the pipeline input to be assigned to the $vm variable. We start the function using the code below.

[CmdletBinding()]
    param
    (
        [Parameter(Mandatory=$true, ValueFromPipeline=$True)] $vm
    )

Next, we need to assign the $vcsa variable the currently connected VI Server session which is stored in a global variable.

$vcsa = $global:DefaultVIServer.Name

We need a VM object so we can get the MoRef ID. Lets now check if $vm is a PowerShell object or a string, if a string assign a VM object.

if ($vm.GetType().Name -eq "String")
  {
      $vm = Get-VM $vm
  }

Now we have the VM object, we can get the MoRef ID property we require for the URL.

$vmID = $vm.id.Split("-")[-1]

And finally, we have to check the VM object to see if we are connected to a vCenter server or an ESXi host then assign the $url variable the appropriate value.

if ($vm.id -like "*vm*")
    {
        $url = "vmrc://" + $creds.username + "@" + $vcsa + ":443/?moid=vm-" + $vmID
    }
    else
    {
        $url = "vmrc://" + $creds.username + "@" + $vcsa + ":443/?moid=" + $vmID
    }

Time to launch using the Start-Process cmdlet.

Start-Process -Path $url

Solution

Many improvements can be made, but for a quick win, it ticks the box. I really hope you have gained something from this article. The complete code can be found on GitHub.

Website code examples
https://github.com/ezrahill/ezrahill.co.uk
2 forks.
1 stars.
0 open issues.

Recent commits:

The FizzBuzz Question?

To be honest, this is new to me and stumbled across FizzBuzz being an interview question for Software Engineering positions on a medium post by Valeri Alexiev entitled “A Software Engineering survival guide”. Thought I would attempt to tackle it personally, seeing as I’m currently learning Python.

What is FizzBuzz?

Put simply, a kids game. Imran Ghory came up with a class of developer interview questions based on FizzBuzz, a kids game, where you count from 1-100, however on the multiples of three you call out ‘Fizz’, and on the multiples of five you call out ‘Buzz’ and on a number where its a multiple of both three and five you holla ‘FizzBuzz’.

An example of one of the FizzBuzz questions:

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”. – Imran Ghory

Overthinking

My attempt at answering the FizzBuzz question above, I thought it best to store it in a list but, in reality, I was over thinking it. In my solution, there is way more I need to explain, can be a little confusing with how I chose to reference the index of the list. My attempt is an example of brute forcing some code to get the job done but doesn’t help moving forwards.

output = list(range(1,101))		# This list will be updated and the output at the end

ref = list(range(0,100))			# Used as a reference for the index

for num in ref[2::3]:				# Start after index 2 and count up in 3s
    output[num] = ["Fizz"]

for num in ref[4::5]:				# Start after index 4 and count up in 5s
    if output[num] == ["Fizz"]:
        output[num] = ["FizzBuzz"]
    else:    
        output[num] = ["Buzz"]

output

After feeling like I succeeded by getting the correct output, I decided to try and do the same in PowerShell by attempting to reuse my code but became stuck as there is not an alternative to the Python range() sequence type in PowerShell that would count in multiples.

So, over to google to look for a PowerShell solution. I found a blog post by Devin Leaman. After taking a peek at their code, it dawned on me that I could use the % (remainder) operator.

For a great explanation about how to tackle the FizzBuzz question, this Tom Scott video on YouTube is worth a watch.

Refined

Using this new found information by losing the List sequence type and making use of the remainder operator you get the below which is way more elegant than what I came up with initially and it translates to PowersShell.

Python

for num in range(1,101):
    output = ""
  
    if num % 3 == 0: output += "Fizz"
    if num % 5 == 0: output += "Buzz"
    if output == "": output = num
  
    print(output)

PowerShell

ForEach-Object ($num in 1..100)
{
    $output = ""
  
    if ($num % 3 -eq 0) { $output += "Fizz" }
    if ($num % 5 -eq 0) { $output += "Buzz" }
    if ($output -eq "") { $output = $num }
  
    Write-Output $output
}

Hope you are visiting after attempting the question yourself 😀