vmsiul
Enthusiast
Enthusiast

Need assistance modifying a PowerCLI script for vRA/vRO

Hello, 

I was wondering if someone could please help with the following query. We are using the following script to enable Virtualization Based Security on a per VM level. 

https://communities.vmware.com/t5/VMware-PowerCLI-Discussions/Turn-on-Virtualization-based-security-...

 

The script is running from within VMware Realize Automation / Orchestration in order to enable VBS as part of an specific workflow. The modified script for vRA/vRO is below. 

The issue that I am having is that VBS can only be enabled when the VM is powered off, in some cases the workflow takes a little longer to run and by then the VM is running already which will make the task (script) to fail. 

That being said, I was looking for some way to improve the script a little bit perhaps by adding something to power off the VM if it's running then execute the code in the script and then bring the VM back on. I feel that with something like this hopefully we will make sure that VBS is enabled when the VM is not running and once VBS is enabled it will turn on the VM to proceed. I have unsuccessfully tried to modify the code but I can't find a way to stop and start the VM successfully. Can someone please help?

Thank you

 

 

// Input: inputProperties from vRA
var enableVBS = inputProperties.customProperties.enableVBS
if (enableVBS == "true") { 
  var name = inputProperties.resourceNames[0]
  var vms = VcPlugin.getAllVirtualMachines(null, name)
  vm = vms[0]

  var bootOpts = new VcVirtualMachineBootOptions()
  var flags = new VcVirtualMachineFlagInfo()
  var spec = new VcVirtualMachineConfigSpec()

  bootOpts.efiSecureBootEnabled = true;
  flags.vbsEnabled = true;
  flags.vvtdEnabled = true;

  spec.firmware = VcGuestOsDescriptorFirmwareType.efi;
  spec.nestedHVEnabled = true;
  spec.bootOptions = bootOpts;
  spec.flags = flags;

  vm.reconfigVM_Task(spec)
}

 

 

 

 

 

 

0 Kudos
12 Replies
LucD
Leadership
Leadership

Moved to the vRealize Automation Tools discussions community


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

0 Kudos
LucD
Leadership
Leadership

My vRA knowledge is non existing, but with PowerCLI you could do something like this

$wasPoweredOn = $false

$vm = Get-VM MyVM

if($vm.PowerState -eq 'PoweredOn'){
  Shutdown-VMGuest -VM $vm -Confirm:$false
  while($vm.PowerState -ne 'PoweredOff'){
    sleep 2
    $vm = Get-VM -Name $vm.Name
  }
  $wasPoweredOn = $true
}

$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.Firmware = [VMware.Vim.GuestOsDescriptorFirmwareType]::efi
$spec.NestedHVEnabled = $true

$boot = New-Object VMware.Vim.VirtualMachineBootOptions
$boot.EfiSecureBootEnabled = $true
$spec.BootOptions = $boot

$flags = New-Object VMware.Vim.VirtualMachineFlagInfo
$flags.VbsEnabled = $true
$flags.VvtdEnabled = $true
$spec.flags = $flags

$vm.ExtensionData.ReconfigVM($spec)

if($wasPoweredOn){
  Start-VM -VM $vm -Confirm:$false
}


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

0 Kudos
vmsiul
Enthusiast
Enthusiast

Thanks LucD! - this seems to be doing it from PowerCLI. But I am unable to run it as is within the vRO workflow, I have tried different ways but no luck.  Maybe someone can help. 

 

0 Kudos
johnbowdre
Enthusiast
Enthusiast

Wrapping your code for doing VBS things with this seems like it should work:

 

var originalState = vm.state;
if (originalState === "poweredOn") {
    System.log("VM was running.")
    function sleep(milliseconds) {
      var timeStart = new Date().getTime();
      while (true) {
         var elapsedTime = new Date().getTime() - timeStart;
         if (elapsedTime > milliseconds) {
            break;
         }
      }
   }
    vm.shutdownGuest();
    while (vm.state != "poweredOff") {
        System.log("VM is stopping...")
        sleep(4000);
        vm = VcPlugin.getAllVirtualMachines(null, name)[0];
    }
}

// Do your VBS stuff

if (originalState === "poweredOn") {
    System.log("VM is starting...")
    vm.powerOnVM_Task();
}

 

 

(JavaScript doesn't have a native `sleep()` function so I shamelessly stole this one from https://automationadmin.com/2020/01/vro-javascript-syntax/)

0 Kudos
vmsiul
Enthusiast
Enthusiast

Hi John - Thank you so much for the help! 

This is the script that I am using as part of the workflow, hopefully I haven't missed anything! I am still getting some odd result sometimes VBS is enabled and some others is not, the workflow runs every time but sometimes the VBS option is not enabled. All I can think of is that the VM is running when the option is enabled. I wonder if there is anything else that can be done. 

 

var originalState = vm.state;
if (originalState === "poweredOn") {
    System.log("VM was running.")
    function sleep(milliseconds) {
      var timeStart = new Date().getTime();
      while (true) {
         var elapsedTime = new Date().getTime() - timeStart;
         if (elapsedTime > milliseconds) {
            break;
         }
      }
   }
    vm.shutdownGuest();
    while (vm.state != "poweredOff") {
        System.log("VM is stopping...")
        sleep(4000);
        vm = VcPlugin.getAllVirtualMachines(null, name)[0];
    }
}

// Input: inputProperties from vRA
var enableVBS = inputProperties.customProperties.enableVBS
if (enableVBS == "true") { 
var name = inputProperties.resourceNames[0]
var vms = VcPlugin.getAllVirtualMachines(null, name)
vm = vms[0]

var bootOpts = new VcVirtualMachineBootOptions()
var flags = new VcVirtualMachineFlagInfo()
var spec = new VcVirtualMachineConfigSpec()

bootOpts.efiSecureBootEnabled = true;
flags.vbsEnabled = true;
flags.vvtdEnabled = true;

spec.firmware = VcGuestOsDescriptorFirmwareType.efi;
spec.nestedHVEnabled = true;
spec.bootOptions = bootOpts;
spec.flags = flags;

if (originalState === "poweredOn") {
    System.log("VM is starting...")
    vm.powerOnVM_Task();
}

vm.reconfigVM_Task(spec)
}

 

 

0 Kudos
Ankush11s
VMware Employee
VMware Employee

@vmsiul 
the Code which is shared by @LucD would work in vRO , May i know what issue you have faced in that 
I assume you would be using on Compute Post Provisioning event .
so all you need is VM name
here is the updated code , I just added 2 lines 

function Handler($context, $inputs) 
{
$MyVM = $input.inputProperties.resourcename[0]
$wasPoweredOn = $false
$vm = Get-VM $MyVM 
if($vm.PowerState -eq 'PoweredOn'){
  Shutdown-VMGuest -VM $vm -Confirm:$false
  while($vm.PowerState -ne 'PoweredOff'){
    sleep 2
    $vm = Get-VM -Name $vm.Name
  }
  $wasPoweredOn = $true
}

$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.Firmware = [VMware.Vim.GuestOsDescriptorFirmwareType]::efi
$spec.NestedHVEnabled = $true

$boot = New-Object VMware.Vim.VirtualMachineBootOptions
$boot.EfiSecureBootEnabled = $true
$spec.BootOptions = $boot

$flags = New-Object VMware.Vim.VirtualMachineFlagInfo
$flags.VbsEnabled = $true
$flags.VvtdEnabled = $true
$spec.flags = $flags

$vm.ExtensionData.ReconfigVM($spec)

if($wasPoweredOn){
  Start-VM -VM $vm -Confirm:$false
}
}

Ankush11s_0-1655443161738.png

 

0 Kudos
Ankush11s
VMware Employee
VMware Employee

Steps to do is 
Login to vRO 
Click on Action => Click on New Action under your desired module
and paste the code .
attaching the reference screenshot.

Ankush11s_1-1655443379661.png

 

Ankush11s_0-1655443345291.png

 

0 Kudos
johnbowdre
Enthusiast
Enthusiast


@vmsiul wrote:

Hi John - Thank you so much for the help! 

This is the script that I am using as part of the workflow, hopefully I haven't missed anything! I am still getting some odd result sometimes VBS is enabled and some others is not, the workflow runs every time but sometimes the VBS option is not enabled. All I can think of is that the VM is running when the option is enabled. I wonder if there is anything else that can be done. 


You'd need to make sure you define the `vm` variable before you try to reference it. So your handling if `inputProperties` needs to happen up top:

 

// Input: inputProperties from vRA
var enableVBS = inputProperties.customProperties.enableVBS
if (enableVBS == "true") { 
  var vmName = inputProperties.resourceNames[0]
  var vms = VcPlugin.getAllVirtualMachines(null, vmName)
  vm = vms[0]
  var originalState = vm.state;
  if (originalState === "poweredOn") {
    System.log("VM was running.")
    function sleep(milliseconds) {
      var timeStart = new Date().getTime();
      while (true) {
        var elapsedTime = new Date().getTime() - timeStart;
        if (elapsedTime > milliseconds) {
          break;
        }
      }
    }
      vm.shutdownGuest();
      while (vm.state != "poweredOff") {
        System.log("VM is stopping...")
        sleep(4000);
        vm = VcPlugin.getAllVirtualMachines(null, vmName)[0];
      }
  }
  var bootOpts = new VcVirtualMachineBootOptions()
  var flags = new VcVirtualMachineFlagInfo()
  var spec = new VcVirtualMachineConfigSpec()
  bootOpts.efiSecureBootEnabled = true;
  flags.vbsEnabled = true;
  flags.vvtdEnabled = true;
  spec.firmware = VcGuestOsDescriptorFirmwareType.efi;
  spec.nestedHVEnabled = true;
  spec.bootOptions = bootOpts;
  spec.flags = flags;
  vm.reconfigVM_Task(spec)
  if (originalState === "poweredOn") {
    System.log("VM is starting...")
    vm.powerOnVM_Task();
  }
}

 

0 Kudos
vmsiul
Enthusiast
Enthusiast

Hi John, 

I apologize, my bad totally misunderstood you reply. I have corrected the script and seems to be working, however I am seeing that when the machine is running it will first power off the VM then power ON and run the reconfigure commands to enable vbs, at that point it will fail because the VM is already in a running state. I can see this behavior in VC. It should be something like check state if it's on then power off then enable vbs and power on. Perhaps for efficiency we just want to do something like power off (no check), execute vbs and power on. 

Thank you so much!

vmsiul_0-1655495691726.png

 

0 Kudos
LucD
Leadership
Leadership

I never tinkered with vRA, but that reconfigVM seems to be at the wrong place.


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

johnbowdre
Enthusiast
Enthusiast

Is Blocking enabled on your extensibility Subscription? That should prevent it from moving on to the next stage in the provisioning task (power on) until your workflow finishes running.

If that's not doing the trick, maybe switch to the "Compute initial power on" event topic to guarantee that your blocking workflow will complete before the VM gets booted.

0 Kudos
johnbowdre
Enthusiast
Enthusiast


@LucD wrote:

I never tinkered with vRA, but that reconfigVM seems to be at the wrong place.


Yep, that too - 100% my bad on that. Good catch. reconfigVM needs to happen before the power on. (I edited the script in the above post to fix that.)

0 Kudos