Run scripts in guest OS with vRA ABX Actions
Thus far in my vRealize Automation project, I've primarily been handing the payload over to vRealize Orchestrator to do the heavy lifting on the back end. This approach works really well for complex multi-part workflows (like when generating unique hostnames), but it may be overkill for more linear tasks (such as just running some simple commands inside of a deployed guest OS). In this post, I'll explore how I use vRA Action Based eXtensibility (ABX) to do just that.
The Goal
My ABX action is going to use PowerCLI to perform a few steps inside a deployed guest OS (Windows-only for this demonstration):
- Auto-update VM tools (if needed).
- Add specified domain users/groups to the local Administrators group.
- Extend the C: volume to fill the VMDK.
- Set up Windows Firewall to enable remote access.
- Create a scheduled task to attempt to automatically apply any available Windows updates.
Template Changes
Cloud Assembly
I'll need to start by updating the cloud template so that the requester can input an (optional) list of admin accounts to be added to the VM, and to enable specifying a disk size to override the default from the source VM template.
I will also add some properties to tell PowerCLI (and the Invoke-VmScript
cmdlet in particular) how to connect to the VM.
Inputs section
I'll kick this off by going into Cloud Assembly and editing the WindowsDemo
template I've been working on for the past few eons. I'll add a diskSize
input:
1formatVersion: 1
2inputs:
3 site: [...]
4 image: [...]
5 size: [...]
6 diskSize:
7 title: 'System drive size'
8 default: 60
9 type: integer
10 minimum: 60
11 maximum: 200
12 network: [...]
13 adJoin: [...]
14[...]
The default value is set to 60GB to match the VMDK attached to the source template; that's also the minimum value since shrinking disks gets messy.
I'll also drop in an adminsList
input at the bottom of the section:
1[...]
2 poc_email: [...]
3 ticket: [...]
4 adminsList:
5 type: string
6 title: Administrators
7 description: Comma-separated list of domain accounts/groups which need admin access to this server.
8 default: ''
9resources:
10 Cloud_vSphere_Machine_1:
11[...]
Resources section
In the Resources section of the cloud template, I'm going to add a few properties that will tell the ABX script how to connect to the appropriate vCenter and then the VM.
vCenter
: The vCenter server where the VM will be deployed, and thus the server which PowerCLI will authenticate against. In this case, I've only got one vCenter, but a larger environment might have multiples. Defining this in the cloud template makes it easy to select automagically if needed. (For instance, if I had abow-vcsa
and adre-vcsa
for my different sites, I could do something likevCenter: '${input.site}-vcsa.lab.bowdre.net'
here.)vCenterUser
: The username with rights to the VM in vCenter. Again, this doesn't have to be a static assignment.templateUser
: This is the account that will be used byInvoke-VmScript
to log in to the guest OS. My template will use the defaultAdministrator
account for non-domain systems, but thelab\vra
service account on domain-joined systems (using theadJoin
input I set up earlier).
I'll also include the adminsList
input from earlier so that can get passed to ABX as well. And I'm going to add in an adJoin
property (mapped to the existing input.adJoin
) so that I'll have that to work with later.
1[...]
2resources:
3 Cloud_vSphere_Machine_1:
4 type: Cloud.vSphere.Machine
5 properties:
6 image: '${input.image}'
7 flavor: '${input.size}'
8 site: '${input.site}'
9 vCenter: vcsa.lab.bowdre.net
10 vCenterUser: vra@lab.bowdre.net
11 templateUser: '${input.adJoin ? "vra@lab" : "Administrator"}'
12 adminsList: '${input.adminsList}'
13 environment: '${input.environment}'
14 function: '${input.function}'
15 app: '${input.app}'
16 adJoin: '${input.adJoin}'
17 ignoreActiveDirectory: '${!input.adJoin}'
18[...]
And I will add in a storage
property as well which will automatically adjust the deployed VMDK size to match the specified input:
1[...]
2 description: '${input.description}'
3 networks: [...]
4 constraints: [...]
5 storage:
6 bootDiskCapacityInGB: '${input.diskSize}'
7 Cloud_vSphere_Network_1:
8 type: Cloud.vSphere.Network
9 properties: [...]
10[...]
Complete template
Okay, all together now:
1formatVersion: 1
2inputs:
3 site:
4 type: string
5 title: Site
6 enum:
7 - BOW
8 - DRE
9 image:
10 type: string
11 title: Operating System
12 oneOf:
13 - title: Windows Server 2019
14 const: ws2019
15 default: ws2019
16 size:
17 title: Resource Size
18 type: string
19 oneOf:
20 - title: 'Micro [1vCPU|1GB]'
21 const: micro
22 - title: 'Tiny [1vCPU|2GB]'
23 const: tiny
24 - title: 'Small [2vCPU|2GB]'
25 const: small
26 default: small
27 diskSize:
28 title: 'System drive size'
29 default: 60
30 type: integer
31 minimum: 60
32 maximum: 200
33 network:
34 title: Network
35 type: string
36 adJoin:
37 title: Join to AD domain
38 type: boolean
39 default: true
40 staticDns:
41 title: Create static DNS record
42 type: boolean
43 default: false
44 environment:
45 type: string
46 title: Environment
47 oneOf:
48 - title: Development
49 const: D
50 - title: Testing
51 const: T
52 - title: Production
53 const: P
54 default: D
55 function:
56 type: string
57 title: Function Code
58 oneOf:
59 - title: Application (APP)
60 const: APP
61 - title: Desktop (DSK)
62 const: DSK
63 - title: Network (NET)
64 const: NET
65 - title: Service (SVS)
66 const: SVS
67 - title: Testing (TST)
68 const: TST
69 default: TST
70 app:
71 type: string
72 title: Application Code
73 minLength: 3
74 maxLength: 3
75 default: xxx
76 description:
77 type: string
78 title: Description
79 description: Server function/purpose
80 default: Testing and evaluation
81 poc_name:
82 type: string
83 title: Point of Contact Name
84 default: Jack Shephard
85 poc_email:
86 type: string
87 title: Point of Contact Email
88 default: jack.shephard@virtuallypotato.com
89 pattern: '^[^\s@]+@[^\s@]+\.[^\s@]+$'
90 ticket:
91 type: string
92 title: Ticket/Request Number
93 default: 4815162342
94 adminsList:
95 type: string
96 title: Administrators
97 description: Comma-separated list of domain accounts/groups which need admin access to this server.
98 default: ''
99resources:
100 Cloud_vSphere_Machine_1:
101 type: Cloud.vSphere.Machine
102 properties:
103 image: '${input.image}'
104 flavor: '${input.size}'
105 site: '${input.site}'
106 vCenter: vcsa.lab.bowdre.net
107 vCenterUser: vra@lab.bowdre.net
108 templateUser: '${input.adJoin ? "vra@lab" : "Administrator"}'
109 adminsList: '${input.adminsList}'
110 environment: '${input.environment}'
111 function: '${input.function}'
112 app: '${input.app}'
113 adJoin: '${input.adJoin}'
114 ignoreActiveDirectory: '${!input.adJoin}'
115 activeDirectory:
116 relativeDN: '${"OU=Servers,OU=Computers,OU=" + input.site + ",OU=LAB"}'
117 customizationSpec: '${input.adJoin ? "vra-win-domain" : "vra-win-workgroup"}'
118 staticDns: '${input.staticDns}'
119 dnsDomain: lab.bowdre.net
120 poc: '${input.poc_name + " (" + input.poc_email + ")"}'
121 ticket: '${input.ticket}'
122 description: '${input.description}'
123 networks:
124 - network: '${resource.Cloud_vSphere_Network_1.id}'
125 assignment: static
126 constraints:
127 - tag: 'comp:${to_lower(input.site)}'
128 storage:
129 bootDiskCapacityInGB: '${input.diskSize}'
130 Cloud_vSphere_Network_1:
131 type: Cloud.vSphere.Network
132 properties:
133 networkType: existing
134 constraints:
135 - tag: 'net:${input.network}'
With the template sorted, I need to assign it a new version and release it to the catalog so that the changes will be visible to Service Broker:
Service Broker custom form
I now need to also make some updates to the custom form configuration in Service Broker so that the new fields will appear on the request form. First things first, though: after switching to the Service Broker UI, I go to Content & Policies > Content Sources, open the linked content source, and click the Save & Import button to force Service Broker to pull in the latest versions from Cloud Assembly.
I can then go to Content, click the three-dot menu next to my WindowsDemo
item, and select the Customize Form option. I drag-and-drop the System drive size
from the Schema Elements section onto the canvas, placing it directly below the existing Resource Size
field.
With the field selected, I use the Properties section to edit the label with a unit so that users will better understand what they're requesting.
On the Values tab, I change the Step option to 5
so that we won't wind up with users requesting a disk size of 62.357 GB
or anything crazy like that.
I'll drag-and-drop the Administrators
field to the canvas, and put it right below the VM description:
I only want this field to be visible if the VM is going to be joined to the AD domain, so I'll set the Visibility accordingly:
That should be everything I need to add to the custom form so I'll be sure to hit that big Save button before moving on.
Extensibility
Okay, now it's time to actually make the stuff work on the back end. But before I get to writing the actual script, there's something else I'll need to do first. Remember how I added properties to store the usernames for vCenter and the VM template in the cloud template? My ABX action will also need to know the passwords for those accounts. I didn't add those to the cloud template since anything added as a property there (even if flagged as a secret!) would be visible in plain text to any external handlers (like vRO). Instead, I'll store those passwords as encrypted Action Constants.
Action Constants
From the vRA Cloud Assembly interface, I'll navigate to Extensibility > Library > Actions and then click the Action Constants button up top. I can then click New Action Constant and start creating the ones I need:
vCenterPassword
: for logging into vCenter.templatePassWinWorkgroup
: for logging into non-domain VMs.templatePassWinDomain
: for logging into VMs with the designated domain credentials.
I'll make sure to enable the Encrypt the action constant value toggle for each so they'll be protected.
Once all those constants are created I can move on to the meat of this little project:
ABX Action
I'll click back to Extensibility > Library > Actions and then + New Action. I give the new action a clever title and description:
I then hit the language dropdown near the top left and select to use powershell
so that I can use those sweet, sweet PowerCLI cmdlets.
And I'll pop over to the right side to map the Action Constants I created earlier so that I can reference them in the script I'm about to write:
Now for The Script:
1<# vRA 8.x ABX action to perform certain in-guest actions post-deploy:
2 Windows:
3 - auto-update VM tools
4 - add specified domain users/groups to local Administrators group
5 - extend C: volume to fill disk
6 - set up remote access
7 - create a scheduled task to (attempt to) apply Windows updates
8
9 ## Action Secrets:
10 templatePassWinDomain # password for domain account with admin rights to the template (domain-joined deployments)
11 templatePassWinWorkgroup # password for local account with admin rights to the template (standalone deployments)
12 vCenterPassword # password for vCenter account passed from the cloud template
13
14 ## Action Inputs:
15 ## Inputs from deployment:
16 resourceNames[0] # VM name [BOW-DVRT-XXX003]
17 customProperties.vCenterUser # user for connecting to vCenter [lab\vra]
18 customProperties.vCenter # vCenter instance to connect to [vcsa.lab.bowdre.net]
19 customProperties.dnsDomain # long-form domain name [lab.bowdre.net]
20 customProperties.adminsList # list of domain users/groups to be added as local admins [john, lab\vra, vRA-Admins]
21 customProperties.adJoin # boolean to determine if the system will be joined to AD (true) or not (false)
22 customProperties.templateUser # username used for connecting to the VM through vmtools [Administrator] / [root]
23#>
24
25function handler($context, $inputs) {
26 # Initialize global variables
27 $vcUser = $inputs.customProperties.vCenterUser
28 $vcPassword = $context.getSecret($inputs."vCenterPassword")
29 $vCenter = $inputs.customProperties.vCenter
30
31 # Create vmtools connection to the VM
32 $vmName = $inputs.resourceNames[0]
33 Connect-ViServer -Server $vCenter -User $vcUser -Password $vcPassword -Force
34 $vm = Get-VM -Name $vmName
35 Write-Host "Waiting for VM Tools to start..."
36 if (-not (Wait-Tools -VM $vm -TimeoutSeconds 180)) {
37 Write-Error "Unable to establish connection with VM tools" -ErrorAction Stop
38 }
39
40 # Detect OS type
41 $count = 0
42 While (!$osType) {
43 Try {
44 $osType = ($vm | Get-View).Guest.GuestFamily.ToString()
45 $toolsStatus = ($vm | Get-View).Guest.ToolsStatus.ToString()
46 } Catch {
47 # 60s timeout
48 if ($count -ge 12) {
49 Write-Error "Timeout exceeded while waiting for tools." -ErrorAction Stop
50 break
51 }
52 Write-Host "Waiting for tools..."
53 $count++
54 Sleep 5
55 }
56 }
57 Write-Host "$vmName is a $osType and its tools status is $toolsStatus."
58
59 # Update tools on Windows if out of date
60 if ($osType.Equals("windowsGuest") -And $toolsStatus.Equals("toolsOld")) {
61 Write-Host "Updating VM Tools..."
62 Update-Tools $vm
63 Write-Host "Waiting for VM Tools to start..."
64 if (-not (Wait-Tools -VM $vm -TimeoutSeconds 180)) {
65 Write-Error "Unable to establish connection with VM tools" -ErrorAction Stop
66 }
67 }
68
69 # Run OS-specific tasks
70 if ($osType.Equals("windowsGuest")) {
71 # Initialize Windows variables
72 $domainLong = $inputs.customProperties.dnsDomain
73 $adminsList = $inputs.customProperties.adminsList
74 $adJoin = $inputs.customProperties.adJoin
75 $templateUser = $inputs.customProperties.templateUser
76 $templatePassword = $adJoin.Equals("true") ? $context.getSecret($inputs."templatePassWinDomain") : $context.getSecret($inputs."templatePassWinWorkgroup")
77
78 # Add domain accounts to local administrators group
79 if ($adminsList.Length -gt 0 -And $adJoin.Equals("true")) {
80 # Standardize users entered without domain as DOMAIN\username
81 if ($adminsList.Length -gt 0) {
82 $domainShort = $domainLong.split('.')[0]
83 $adminsArray = @(($adminsList -Split ',').Trim())
84 For ($i=0; $i -lt $adminsArray.Length; $i++) {
85 If ($adminsArray[$i] -notmatch "$domainShort.*\\" -And $adminsArray[$i] -notmatch "@$domainShort") {
86 $adminsArray[$i] = $domainShort + "\" + $adminsArray[$i]
87 }
88 }
89 $admins = '"{0}"' -f ($adminsArray -join '","')
90 Write-Host "Administrators: $admins"
91 }
92 $adminScript = "Add-LocalGroupMember -Group Administrators -Member $admins"
93 Start-Sleep -s 10
94 Write-Host "Attempting to add administrator accounts..."
95 $runAdminScript = Invoke-VMScript -VM $vm -ScriptText $adminScript -GuestUser $templateUser -GuestPassword $templatePassword
96 if ($runAdminScript.ScriptOutput.Length -eq 0) {
97 Write-Host "Successfully added [$admins] to Administrators group."
98 } else {
99 Write-Host "Attempt to add [$admins] to Administrators group completed with warnings:`n" $runAdminScript.ScriptOutput "`n"
100 }
101 } else {
102 Write-Host "No admins to add..."
103 }
104 # Extend C: volume to fill system drive
105 $partitionScript = "`$Partition = Get-Volume -DriveLetter C | Get-Partition; `$Partition | Resize-Partition -Size (`$Partition | Get-PartitionSupportedSize).sizeMax"
106 Start-Sleep -s 10
107 Write-Host "Attempting to extend system volume..."
108 $runPartitionScript = Invoke-VMScript -VM $vm -ScriptText $partitionScript -GuestUser $templateUser -GuestPassword $templatePassword
109 if ($runPartitionScript.ScriptOutput.Length -eq 0) {
110 Write-Host "Successfully extended system partition."
111 } else {
112 Write-Host "Attempt to extend system volume completed with warnings:`n" $runPartitionScript.ScriptOutput "`n"
113 }
114 # Set up remote access
115 $remoteScript = "Enable-NetFirewallRule -DisplayGroup `"Remote Desktop`"
116 Enable-NetFirewallRule -DisplayGroup `"Windows Management Instrumentation (WMI)`"
117 Enable-NetFirewallRule -DisplayGroup `"File and Printer Sharing`"
118 Enable-PsRemoting
119 Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name `"fDenyTSConnections`" -Value 0"
120 Start-Sleep -s 10
121 Write-Host "Attempting to enable remote access (RDP, WMI, File and Printer Sharing, PSRemoting)..."
122 $runRemoteScript = Invoke-VMScript -VM $vm -ScriptText $remoteScript -GuestUser $templateUser -GuestPassword $templatePassword
123 if ($runRemoteScript.ScriptOutput.Length -eq 0) {
124 Write-Host "Successfully enabled remote access."
125 } else {
126 Write-Host "Attempt to enable remote access completed with warnings:`n" $runRemoteScript.ScriptOutput "`n"
127 }
128 # Create scheduled task to apply updates
129 $updateScript = "`$action = New-ScheduledTaskAction -Execute 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' -Argument '-NoProfile -WindowStyle Hidden -Command `"& {Install-WUUpdates -Updates (Start-WUScan)}`"'
130 `$trigger = New-ScheduledTaskTrigger -Once -At ([DateTime]::Now.AddMinutes(1))
131 `$settings = New-ScheduledTaskSettingsSet -Compatibility Win8 -Hidden
132 Register-ScheduledTask -Action `$action -Trigger `$trigger -Settings `$settings -TaskName `"Initial_Updates`" -User `"NT AUTHORITY\SYSTEM`" -RunLevel Highest
133 `$task = Get-ScheduledTask -TaskName `"Initial_Updates`"
134 `$task.Triggers[0].StartBoundary = [DateTime]::Now.AddMinutes(1).ToString(`"yyyy-MM-dd'T'HH:mm:ss`")
135 `$task.Triggers[0].EndBoundary = [DateTime]::Now.AddHours(3).ToString(`"yyyy-MM-dd'T'HH:mm:ss`")
136 `$task.Settings.AllowHardTerminate = `$True
137 `$task.Settings.DeleteExpiredTaskAfter = 'PT0S'
138 `$task.Settings.ExecutionTimeLimit = 'PT2H'
139 `$task.Settings.Volatile = `$False
140 `$task | Set-ScheduledTask"
141 Start-Sleep -s 10
142 Write-Host "Creating a scheduled task to apply updates..."
143 $runUpdateScript = Invoke-VMScript -VM $vm -ScriptText $updateScript -GuestUser $templateUser -GuestPassword $templatePassword
144 Write-Host "Created task:`n" $runUpdateScript.ScriptOutput "`n"
145 } elseif ($osType.Equals("linuxGuest")) {
146 #TODO
147 Write-Host "Linux systems not supported by this action... yet"
148 }
149 # Cleanup connection
150 Disconnect-ViServer -Server $vCenter -Force -Confirm:$false
151
152}
I like to think that it's fairly well documented (but I've also been staring at / tweaking this for a while); here's the gist of what it's doing:
- Capture vCenter login credentials from the Action Constants and the
customProperties
of the deployment (from the cloud template). - Use those creds to
Connect-ViServer
to the vCenter instance. - Find the VM object which matches the
resourceName
from the vRA deployment. - Wait for VM tools to be running and accessible on that VM.
- Determine the OS type of the VM (Windows/Linux).
- If it's Windows and the tools are out of date, update them and wait for the reboot to complete.
- If it's Windows, move on:
- If it needs to add accounts to the Administrators group, assemble the needed script and run it in the guest via
Invoke-VmScript
. - Assemble a script to expand the C: volume to fill whatever size VMDK is attached as HDD1, and run it in the guest via
Invoke-VmScript
. - Assemble a script to set common firewall exceptions for remote access, and run it in the guest via
Invoke-VmScript
. - Assemble a script to schedule a task to (attempt to) apply Windows updates, and run it in the guest via
Invoke-VmScript
.
It wouldn't be hard to customize the script to perform different actions (or even run against Linux systems - just set $whateverScript = "apt update && apt upgrade"
(or whatever) and call it with $runWhateverScript = Invoke-VMScript -VM $vm -ScriptText $whateverScript -GuestUser $templateUser -GuestPassword $templatePassword
), but this is as far as I'm going to take it for this demo.
Event subscription
Before I can test the new action, I'll need to first add an extensibility subscription so that the ABX action will get called during the deployment. So I head to Extensibility > Subscriptions and click the New Subscription button.
I'll be using this to call my new configureGuest
action - so I'll name the subscription Configure Guest
. I tie it to the Compute Post Provision
event, and bind my action:
I do have another subsciption on that event already, VM Post-Provisioning
which is used to modify the VM object with notes and custom attributes. I'd like to make sure that my work inside the guest happens after that other subscription is completed, so I'll enable blocking and give it a priority of 2
:
After hitting the Save button, I go back to that other VM Post-Provisioning
subscription, set it to enable blocking, and give it a priority of 1
:
This will ensure that the new subscription fires after the older one completes, and that should avoid any conflicts between the two.
Testing
Alright, now let's see if it worked. I head into Service Broker to submit the deployment request:
Note that I've set the disk size to 65GB (up from the default of 60), and I'm adding lab\testy
as a local admin on the deployed system.
Once the deployment finishes, I can switch back to Cloud Assembly and check Extensibility > Activity > Action Runs and then click on the configureGuest
run to see how it did.
It worked!
The Log tab lets me see the progress as the execution progresses:
1Logging in to server.
2logged in to server vcsa.lab.bowdre.net:443
3Read-only file system
409/03/2021 19:08:27 Get-VM Finished execution
509/03/2021 19:08:27 Get-VM
6Waiting for VM Tools to start...
709/03/2021 19:08:29 Wait-Tools 5222b516-ae2c-5740-2926-77cd21441f27
809/03/2021 19:08:29 Wait-Tools Finished execution
909/03/2021 19:08:29 Wait-Tools
1009/03/2021 19:08:29 Get-View Finished execution
1109/03/2021 19:08:29 Get-View
1209/03/2021 19:08:29 Get-View Finished execution
1309/03/2021 19:08:29 Get-View
14BOW-PSVS-XXX001 is a windowsGuest and its tools status is toolsOld.
15Updating VM Tools...
1609/03/2021 19:08:30 Update-Tools 5222b516-ae2c-5740-2926-77cd21441f27
1709/03/2021 19:08:30 Update-Tools Finished execution
1809/03/2021 19:08:30 Update-Tools
19Waiting for VM Tools to start...
2009/03/2021 19:09:00 Wait-Tools 5222b516-ae2c-5740-2926-77cd21441f27
2109/03/2021 19:09:00 Wait-Tools Finished execution
2209/03/2021 19:09:00 Wait-Tools
23Administrators: "lab\testy"
24Attempting to add administrator accounts...
2509/03/2021 19:09:10 Invoke-VMScript 5222b516-ae2c-5740-2926-77cd21441f27
2609/03/2021 19:09:10 Invoke-VMScript Finished execution
2709/03/2021 19:09:10 Invoke-VMScript
28Successfully added ["lab\testy"] to Administrators group.
29Attempting to extend system volume...
3009/03/2021 19:09:27 Invoke-VMScript 5222b516-ae2c-5740-2926-77cd21441f27
3109/03/2021 19:09:27 Invoke-VMScript Finished execution
3209/03/2021 19:09:27 Invoke-VMScript
33Successfully extended system partition.
34Attempting to enable remote access (RDP, WMI, File and Printer Sharing, PSRemoting)...
3509/03/2021 19:09:49 Invoke-VMScript 5222b516-ae2c-5740-2926-77cd21441f27
3609/03/2021 19:09:49 Invoke-VMScript Finished execution
3709/03/2021 19:09:49 Invoke-VMScript
38Successfully enabled remote access.
39Creating a scheduled task to apply updates...
4009/03/2021 19:10:12 Invoke-VMScript 5222b516-ae2c-5740-2926-77cd21441f27
4109/03/2021 19:10:12 Invoke-VMScript Finished execution
4209/03/2021 19:10:12 Invoke-VMScript
43Created task:
44
45TaskPath TaskName State
46-------- -------- -----
47\ Initial_Updates Ready
48\ Initial_Updates Ready
So it claims to have successfully updated the VM tools, added lab\testy
to the local Administrators
group, extended the C:
volume to fill the 65GB virtual disk, added firewall rules to permit remote access, and created a scheduled task to apply updates. I can open a console session to the VM to spot-check the results.
testy
is an admin now!
C:
fills the disk!
Wrap-up
This is really just the start of what I've been able to do in-guest leveraging Invoke-VmScript
from an ABX action. I've got a slightly-larger version of this script which also performs similar actions in Linux guests as well. And I've also cobbled together ABX solutions for generating randomized passwords for local accounts and storing them in an organization's password management solution. I would like to get around to documenting those here in the future... we'll see.
In any case, hopefully this information might help someone else to get started down this path. I'd love to see whatever enhancements you are able to come up with!
More vRA8
- Getting Started with the vRealize Automation REST API
- Fixing 403 error on SaltStack Config 8.6 integrated with vRA and vIDM
- Run scripts in guest OS with vRA ABX Actions
- Notes on vRA HA with NSX-ALB
- Creating static records in Microsoft DNS from vRealize Automation
- Joining VMs to Active Directory in site-specific OUs with vRA8
- See all vRA8