Hi,
I just deployed the brand new vRO 8.1 appliance and did the initial configuration. The “validate configuration” shows only green checkmarks. I desperately wanted to try out the new PowerShell support for scriptable tasks and actions.
I created a simple workflow without any in- or outputs and just one scriptable task. The scriptable tasks is set to PowerCLI11 (PowerShell 6.2) runtime. I modified the auto-generated code and added one line “Get-Module –ListAvailable”.
Code:
function Handler($context, $inputs) {
$inputsString = $inputs | ConvertTo-Json -Compress
Write-Host "Inputs were $inputsString"
Get-Module -ListAvailable
$output=@{status = 'done'}
return $output
}
When I run this the workflow fails with the following error:
2020-04-14 20:47:51.000 +02:00INFO__item_stack:/item1
2020-04-14 20:47:55.000 +02:00INFOInputs were {}
2020-04-14 20:47:57.000 +02:00ERROR/var/run/vco-polyglot/entrypoint.sh: line 9: 6 Killed pwsh -NoProfile -NonInteractive index.ps1 "$@"
2020-04-14 20:47:57.000 +02:00ERRORError in (Workflow:Test 1 / Scriptable task (item1)#12758) Wrapped ch.dunes.scripting.server.polyglot.PolyglotRunner$PolyglotRunnerException: Function was stopped. Most likely because it hit an OOM (out of memory) condition.
2020-04-14 20:47:57.000 +02:00ERRORWorkflow execution stack:
***
item: 'Test 1/item1', state: 'failed', business state: 'null', exception: 'Wrapped ch.dunes.scripting.server.polyglot.PolyglotRunner$PolyglotRunnerException: Function was stopped. Most likely because it hit an OOM (out of memory) condition. (Workflow:Test 1 / Scriptable task (item1)#12758)'
workflow: 'Test 1' (6ff6be6d-2741-4dc0-9552-6a9b6fab9e80)
| 'no inputs'
| 'no outputs'
| 'no attributes'
*** End of execution stack.
When I remove the Get-Module line, the workflow doesn't fail.
I tried to use the cmdlet Connect-VIServer but hit the above same error.
Is anyone out there experiencing the same issue or should I just open a SR with GSS?
With the new scripts the concept of limits was introduced to make sure that a script doesn't take up more resources than necessary. The default memory limit for new runtimes is 64MB, and in many cases this is good enough, but some PowerCLI cmdlets require more, so in these cases it is advices to increase it.
Please, increase the memory limit to something like 256MB (the right side of the action editor) and try again.
This was literally just made available today, so I'd say if you're going to live on the bleeding edge then you should just go straight to GSS.
What is this? Another customer expecting for things to work as advertised in the release notes? Please submit your error report to support and wait for your hotfix like everyone else.
With the new scripts the concept of limits was introduced to make sure that a script doesn't take up more resources than necessary. The default memory limit for new runtimes is 64MB, and in many cases this is good enough, but some PowerCLI cmdlets require more, so in these cases it is advices to increase it.
Please, increase the memory limit to something like 256MB (the right side of the action editor) and try again.
Thanks for providing the solution. It is working now.
I tested two things. Listing all modules with an action:
function Handler() {
Write-Host "List available modules"
Get-Module -ListAvailable | Sort-Object Name | foreach {
Write-Host $_.Name $_.Version
}
}
Connecting to vCenter and listing all VM names (inputs mapped to config elements):
function Handler($context, $inputs) {
# Set PowerCLI config
Write-Host "Set PowerCLI config"
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -ParticipateInCeip:$false -Scope Session -Confirm:$false
# Connect to vCenter
Write-Host "Connect to vCenter"
Connect-VIServer -Server $inputs.vcenter -User $inputs.user -Password $inputs.pass
# Get all VM names
Write-Host "Get VMs"
Get-VM | Sort-Object Name | foreach {
Write-Host $_.Name
}
}
I'm using the foreach { Write-Host $_.Name} because Format-Table output is not shown in the log. Is this a PowerShell things because it is running in NonInteractive mode or is this a bug in vRO?
Format-Table output is not shown in the log. Is this a PowerShell things because it is running in NonInteractive mode
exactly, in an (non interactive) script mode, to bring the outputs of format table, pipe it with | Out-Host
so it becomes something like:
$value | Format-Table | Out-Host
Thank you, it is working quite well!
Is there a documentation for PowerShell support in vRO?
This is the official documentation that covers:
Core Concepts for Python, Node.js, and PowerShell Scripts
Create a PowerShell Script That Calls the vRealize Automation Project API
Thank you for sharing these really useful links! The mapping of Invoke-RestMethod results to output properties is really helpful and is working instantly.
If somebody else wants to try it out, this is my test code with a return type of properties.
function Handler($context, $inputs) {
$r = Invoke-RestMethod -Method GET -Uri "http://api.open-notify.org/astros.json" -Proxy "http://your.proxy:3128"
return $r
}
Since we have a pro at hand, would you mind answering the following additional question, so we can share your knowledge publicly?
1.
Your second link describes the way of uploading actions with modules included, can the once imported modules be used by other PowerShell actions or does every action with modules need to have all modules included themselves?
I’ve already tried to install modules in actions, which is working with this line of code.
Install-Module -Name ImportExcel -Scope CurrentUser -Confirm:$false -AcceptLicense -Proxy http://your.proxy:3128
But my guess is that these can’t be saved permanently that way, or is there a way?
2.
Is it possible to use something like the System object in JS ES5 runtime to access modules, actions, config- and resource elements?
3.
Mapping a VC object (like a VM object) as input for a PowerShell Action is not working. Will or can this ever work?
My guess would have been that I at lease can get the moref or name and type of that object.
Currently the action will fail with the following error.
Error: Wrapped java.lang.RuntimeException: Infinite recursion (StackOverflowError) (through reference chain: java.util.HashMap["vm"]->ch.dunes.vso.sdk.DynamicWrapper["javaObject"]->com.vmware.o11n.plugin.vsphere_gen.VirtualMachine_Wrapper["internalId"]->com.vmware.o11n.sdk.modeldriven.Sid["id"]->com.vmware.o11n.sdk.modeldriven.Sid["id"]->com.vmware.o11n.sdk.modeldriven.Sid["id"]-
Thanks again for you help!
Since we have a pro at hand
I'll try my best
can the once imported modules be used by other PowerShell actions or does every action with modules need to have all modules included themselves?
The latter, scripts for the new runtimes run in isolated environment. Every action/script needs to have its dependencies bundled themselves.
But my guess is that these can’t be saved permanently that way, or is there a way?
This is not recommended, as the same script will be executed upon every action run in a clean environment, this means that the external module will be downloaded and installed every time, which will result in slow (maybe also flaky because of networking) runs.
The recommended way is to have all dependencies already prepared (in a local/shared dev environment) and included in the bundle. Although a bit of inconvenient, it reduces the risk of networking issues, as well as unexpected incompatible versions of 3rd party dependencies (i.e. install module without specifying a version, so that next time the script is ran it could download a newer version).
Is it possible to use something like the System object in JS ES5 runtime to access modules, actions, config- and resource elements?
It is not, for now the way to go is call back vRO's REST API (with API token) if you need to retrieve something runtime. But any feedback on what specifically you want to access is welcomed.
Mapping a VC object (like a VM object) as input for a PowerShell Action is not working. Will or can this ever work?
This is known limitation, the supported inputs types are listed in the document I shared. If I can suggest a work-around - in a workflow, use a standard JS scripting element that accepts any input, extract the properties you are interested in (like you said moref and name) and pass the new it to the next PowerShell/Python/Node element
Very happy to see such interest in this new functionality!
Thank you again for answering my questions. I hope other vRO users can benefit from your answers too. This is truly helpful.
About my question 2, my use case is to access config elements and your proposed way of using the vRO API is working on the first try. That is why I love using PowerShell, this combinded with vROs functionality makes and outstanding product which you should promote alot
I want to share my findings so others can use this go get startet with using PowerShell in vRO.
1. Create a test configuration to query from PowerShell.
2. Create configuration with parameters for the vRO REST API call.
3. Create a PowerShell action with inputs for above config element variables. Return type is properties.
This is the code:
function Handler($context, $inputs) {
# Build authentication header
Write-Host "Build authentication header for user $($inputs.user)"
$authToken = "Basic $([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("$($inputs.user):$($inputs.pass)")))"
$headers = @{
"Authorization" = $authToken
"Content-Type" = "application/json"
"Accept"="application/json"
}
# Get configurations
Write-Host "Get all configurations from $($inputs.url)"
$getConfigParams = @{
Method = "Get"
Uri = "$($inputs.url)/api/configurations"
Headers = $headers
SkipCertificateCheck = $true
}
$responseGetConfigurations = Invoke-RestMethod @getConfigParams
# Get configuration by name
$configName = "TestConfiguration"
Write-Host "Get configuration $configName"
$configUrl = ($responseGetConfigurations.link | Where-Object {$_.attributes.value -eq $configName}).href
$getConfigByNameParams = @{
Method = "Get"
Uri = $configUrl
Headers = $headers
SkipCertificateCheck = $true
}
$responseGetConfigByName = Invoke-RestMethod @getConfigByNameParams
# Create custom object from response
$configObject = @()
$responseGetConfigByName.attributes | ForEach-Object {
$configObject += [PSCustomObject]@{
Name = $_.name
Type = $_.type
Value = $_.value.psobject.Properties.value.value
}
}
# Output object
$configObject | Format-Table | Out-Host
$returnObject = [PSCustomObject]@{
Name = $configName
Elements = $configObject
}
return $returnObject
}
4. Create a workflow and map the url, user and pass variables to the above config elements. Create a output variable of type properties to catch the result of the action.
5. Place the action on the workflow schema and map inputs and outputs.
6. Run the workflow and see the results
I have just noticed in the released notes that the additional scripting language (powershell, python & node.js) are only available for vRealize Automation license, is this likely to change for people that do not have vRA.
V00Z11 That looks great, thanks for sharing! I could only suggest to simplify the need of the url input, you can use $context.vcoUrl
vfk Yes, vRA license is needed now, I don't know anything else.
maverix7 Thanks for the hint. I incorporated this and modified a few other things. Only the user and pass inputs are needed now.
function Handler($context, $inputs) {
# Validate input
if ((-Not $inputs.user) -or (-not $inputs.pass)) {
throw "Username or password missing"
}
# Build credential object
$credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $inputs.user, (ConvertTo-SecureString -String $inputs.pass -AsPlainText -Force)
# Get configurations
$getConfigParams = @{
Method = "Get"
Uri = "$($context.vcoUrl)/api/configurations"
AllowUnencryptedAuthentication = $true
Authentication = "Basic"
ContentType = "application/json"
Credential = $credentials
}
Write-Host "Get all configurations from $($getConfigParams.Uri)"
try {
$responseGetConfigurations = Invoke-RestMethod @getConfigParams
} catch {
throw "Failed to get all configuration"
}
# Find configuration in response
$configName = "TestConfiguration"
$configUrl = ($responseGetConfigurations.link | Where-Object {$_.attributes.value -eq $configName}).href
if (-not $configUrl) {
throw "Cannot find configuration $configName"
}
# Get configuration by name
$getConfigByNameParams = @{
Method = "Get"
Uri = $configUrl
AllowUnencryptedAuthentication = $true
Authentication = "Basic"
ContentType = "application/json"
Credential = $credentials
}
Write-Host "Get configuration $configName"
try {
$responseGetConfigByName = Invoke-RestMethod @getConfigByNameParams
} catch {
throw "Failed to get configuration"
}
# Create custom object from response
$configObject = @()
$responseGetConfigByName.attributes | ForEach-Object {
$configObject += [PSCustomObject]@{
Name = $_.name
Type = $_.type
Value = $_.value.psobject.Properties.value.value
}
}
# Output object to log
$configObject | Format-Table | Out-Host
# Return to output properties
$returnObject = [PSCustomObject]@{
Name = $configName
Elements = $configObject
}
return $returnObject
}
very nice, but this only available to vRA customers which is such disappointment; and crippling for such wonderful addition for vRO.
I suspect the uptake would be far greater if it was available with the standard vCenter license, and more people would be able to provide feedback/feature request as result.
Hi,
are the runtime limits only configured for actions elements? Where can I edit those values for the Workflow Powershell Scripting Elements.
Thank you in advance
BR
Dimi
Currently these limit configurations are available for actions only
Thank you
Thank you so much for this post. I've been running into so many weird errors before I found this post about the out of memory condition and now my vRO powershell actions work as expected after increasing the memory limit to 512. Yes, I had to go to 512 because things were still failing intermittently set at 256. For context, I am not doing anything crazy; connecting to vcenter (connect-viserver), adding disks (New-HardDisk) and then passing in a diskpart script to format/label/letter the new disks with Invoke-VMScript.