Skip to content

noahfarshad/ansible-inventory-generators

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ansible Inventory Generators

Python scripts and vRO workflows that build the Ansible inventories used by the Windows post-deploy pipeline. Two source systems are supported — VMware vSphere and HPE OneView — each with a Python generator that runs on the Ansible control node and a vRO workflow that triggers it on demand.

These run upstream of the Windows post-deploy automation. The inventories they produce are what ansible-playbook -i inventories/Prod/... reads when Aria kicks off windows_postdeploy.yml for a new VM.


Directory Layout

Ansible_Inventory_Generators/
├── README.md                                     This file
├── vsphere/
│   ├── Create-ansible-inventory-from-vSphere.py  Python generator (lives on Ansible control node)
│   ├── Get-all-VMs-from-vCenter.js               vRO scriptable task (triggers the Python script)
│   └── push_inventory_to_bitbucket.js            vRO scriptable task (commits inventory to Bitbucket)
├── oneview/
│   ├── generate_oneview_inventory.py             Python generator for OneView 6.6, 8.9, 10.0
│   └── vro_workflow.js                           vRO scriptable task (triggers the Python script)
└── vro-package/
    └── ansible_inventory_generators.package      Signed vRO .package file — importable as-is into vRO

How These Fit In

┌─────────────────────────────────────────────────────────────────┐
│ Trigger: operator runs the vRO workflow from Assembler          │
│   - "Generate Ansible Inventory from vSphere"                   │
│   - "Generate Ansible Inventory from OneView"                   │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│ vRO scriptable task opens SSH to ansible.example.com │
│ Runs python3 /home/ansible/inventories/{vsphere|oneview}/       │
│   generate_*.py --<args> >logs/inventory_<timestamp>.log        │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│ Python script connects to the source system (vCenter or OneView)│
│ Enumerates VMs/servers, groups by OS / cluster / folder / HW    │
│ Writes INI-format inventory file to /home/ansible/inventories/  │
└─────────────────────────────────────────────────────────────────┘
                              ↓ (vSphere only, optional step)
┌─────────────────────────────────────────────────────────────────┐
│ Second scriptable task: push_inventory_to_bitbucket             │
│ git add / commit / push to github.com/noahfarshad              │
│ Version-controlled history of every inventory generation        │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│ Ansible reads the generated inventory on next playbook run      │
│ windows_postdeploy.yml -> --inventory inventories/Prod/...      │
└─────────────────────────────────────────────────────────────────┘

The generators run on a cadence (scheduled or manual) or when the environment changes enough that the inventory would drift from reality. They are not called during a VM deployment — the post-deploy playbook uses the already-present inventory file at /home/ansible/production/ansible/playbooks/inventories/Prod/hosts.


vSphere Generator

Create-ansible-inventory-from-vSphere.py

Location on control node: /home/ansible/inventories/vsphere/generate_vsphere_inventory.py Language: Python 3 Dependencies: pyvmomi, PyYAML Author: Noah Farshad

What it does: Connects to a vCenter, enumerates every VM (powered-on and off, unless filtered), extracts IP addresses, folder path, cluster, OS guest identity, and resource pool metadata. Groups VMs into Ansible inventory groups by folder hierarchy, OS type, and environment. Writes an INI-format inventory file.

Inputs:

Argument Required Purpose
--vcenter-host yes vCenter FQDN or IP
--vcenter-user yes Username for vCenter auth
--vcenter-password yes Password
--inventory-dir no Output directory (default: /home/ansible/inventories/vsphere)
--environment no Environment label (dev/test/prod), applied to group names (default: prod)
--skip-templates no Omit VM templates from the inventory
--require-ip no Only include VMs that have a guest IP (skips powered-off VMs without cached IPs)
--skip-powered-off no Omit powered-off VMs entirely
--validate-certs no Validate vCenter SSL cert (default: false)

How IPs are resolved: Iterates vm.guest.net, collects all IPv4 addresses, filters out link-local (169.254.x.x) and IPv6. Multiple IPs per VM land as separate inventory attributes.

How groups are built: VM folder path drives the primary group name (e.g., TX-CORP-IT/AUTH/PRD becomes tx_corp_it_auth_prd). OS guest family gives a secondary group (windows, linux). All VMs also land in an all group for broad playbook targeting.

Get-all-VMs-from-vCenter.js

Context: vRO scriptable task, first element in the "Generate Ansible Inventory from vSphere" workflow. Purpose: SSH into the Ansible control node and execute the Python script with parameters passed from the vRO workflow form.

Inputs (from the vRO form):

Parameter Type Example
vCenter VC:SdkConnection Selected from the vRO inventory dropdown
vCenter_username string administrator@vsphere.local
vCenter_password SecureString
ansible_password SecureString SSH password for the ansible user on the control node

What it does:

  1. Extracts the vCenter hostname from the VC:SdkConnection object
  2. Derives the environment name from the vCenter short name (first DNS label)
  3. Opens an SSHSession to ansible.example.com as user ansible
  4. Cleans up old /tmp/inventory_output_*.log files (keeps the latest 10)
  5. Runs the Python script with the parsed arguments, redirecting output to a timestamped log
  6. Outputs the inventory file path and log file path for downstream workflow use

Hardcoded defaults:

  • Ansible host: ansible.example.com
  • Ansible user: ansible
  • Python binary: python3.11
  • Script path: /home/ansible/inventories/vsphere/generate_vsphere_inventory.py

Change these at the top of the script if the control node is reconfigured.

push_inventory_to_bitbucket.js

Context: vRO scriptable task, second (optional) element in the vSphere inventory workflow. Purpose: Commit the freshly-generated inventory to the Essential Coach Bitbucket repo for version control.

Inputs:

Parameter Type Example
vCenter VC:SdkConnection Used to derive commit message
ansibleHost string ansible.example.com
ansibleUsername string ansible
ansible_password SecureString SSH password
bitbucketToken SecureString Bitbucket API token for git push auth
bitbucketRepoUrl string github.com/noahfarshad/scm/hsia/vmware-automation-ansible.git

What it does:

  1. SSHes to the Ansible control node
  2. Runs git add, git commit -m "Inventory update for <vcenter> at <timestamp>", and git push against the Bitbucket repo using the API token
  3. Returns changesPushed: true/false so the workflow can report whether anything actually changed
  4. Handles the no-op case (inventory identical to last commit) gracefully

Safety: The token is a SecureString and is passed into the git remote URL only at runtime — not stored on disk.


OneView Generator

generate_oneview_inventory.py

Location on control node: /home/ansible/inventories/oneview/generate_oneview_inventory.py Language: Python 3 Dependencies: requests, PyYAML, urllib3 Supports: HPE OneView versions 6.6, 8.9, and 10.0

Why three versions: Essential Coach runs a mixed OneView fleet. Each version has a different required X-API-Version header value:

OneView Version X-API-Version
6.6 3800
8.9 6400
10.0 7600

The script reads --version and maps it to the right header automatically via the API_VERSIONS dict.

Inputs:

Argument Env var Required Purpose
--oneview-host ONEVIEW_HOST yes OneView appliance FQDN
--oneview-user ONEVIEW_USER yes Username (prefix local\ for local accounts, domain\ for AD)
--oneview-password ONEVIEW_PASSWORD yes Password
--version ONEVIEW_VERSION yes OneView version: 6.6, 8.9, or 10.0
--local-account no Boolean — use OneView local account (default true)
--output-dir INVENTORY_DIR no Where to write the inventory file

What it does:

  1. Authenticates via /rest/login-sessions with the appropriate API version header
  2. Enumerates server hardware (/rest/server-hardware) and server profiles (/rest/server-profiles)
  3. Extracts iLO addresses, hostnames, server models, power state, and profile templates
  4. Groups servers by model, enclosure, and profile template into Ansible inventory groups
  5. Writes YAML-format inventory (OneView inventories tend to be smaller and more structured than vSphere; YAML is easier to read for this use case)

Authentication variants:

  • Local OneView account (default): Administrator on the OneView appliance itself
  • Directory-integrated: prefix the username with the directory name (e.g., corp.example.com\ansible-svc)

vro_workflow.js

Context: vRO scriptable task — the single element inside the "Generate Ansible Inventory from OneView" workflow. Purpose: SSH into the control node and trigger the OneView Python generator.

Inputs (from the vRO form):

Parameter Type Example
oneviewHost string oneview-tx01.example.com
oneviewUsername string Administrator
oneviewPassword SecureString
oneviewVersion string 8.9 (or 6.6 / 10.0)
ansible_password SecureString SSH password
useLocalAccount boolean true for local OneView admin, false for directory

What it does:

  1. Validates all inputs (throws early if missing)
  2. Opens SSH to ansible.example.com as ansible
  3. Derives a log file name from the OneView short name + ISO timestamp
  4. Runs python3 /home/ansible/inventories/oneview/generate_oneview_inventory.py with all arguments
  5. Streams output back into vRO's System.log for visibility in the workflow run
  6. Returns the inventory path, log path, and execution status (SUCCESS/FAILED)

vRO Package File

vro-package/ansible_inventory_generators.package is the signed vRO export of the two workflows. It is the deployable artifact — import this into a fresh vRO and you get both workflows, their input forms, parameter definitions, and embedded scripts wired up exactly as they run today.

Contents (according to the export manifest):

Workflow UUID Scripts
Generate Ansible Inventory from vSphere eb56b31b-9e69-4c3d-b801-f942ced445b7 Get-all-VMs + push_inventory_to_bitbucket
Generate Ansible Inventory from OneView 9fa43a16-caab-4679-9011-da9fde1533ae vro_workflow (single scripted task)

Signed with: CN=vRO vco-app-67d64887c5-tx99n (VMware-issued certificate).

Importing on a fresh vRO

  1. vRO Client → Actions → Import Package
  2. Select ansible_inventory_generators.package
  3. Accept the signing certificate (the CN above is VMware's, not a forgery risk — but confirm with your security team)
  4. Resolve any conflicts if prior versions exist (usually "Keep Server" unless intentionally replacing)
  5. Both workflows appear under the default location; move them into your Essential Coach folder structure as needed

Source vs. deployable split

The raw .js and .py files in vsphere/ and oneview/ are the editable source — they're what a developer opens, edits, commits to git, and pastes into vRO when making changes. The .package file is the snapshot of what's currently deployed. If these drift, the source files in this folder are the ones to trust — the package should be re-exported after any script change.


Dependencies on the Ansible Control Node

Python packages

# vSphere
pip3 install pyvmomi pyyaml

# OneView
pip3 install requests pyyaml urllib3

File layout expected by the vRO scripts

/home/ansible/inventories/
├── vsphere/
│   └── generate_vsphere_inventory.py    Copy of Create-ansible-inventory-from-vSphere.py
└── oneview/
    └── generate_oneview_inventory.py    Direct copy

Rename on deploy — the vRO scripts hardcode generate_vsphere_inventory.py (dropping the "Create-ansible-inventory-from-" prefix). The OneView script keeps its original name.

SSH access

The ansible user on ansible.example.com must accept password auth from the vRO appliance's outbound IP. If SSH keys are used instead of passwords, the vRO scripts need to switch from session.connectWithPassword(...) to a key-based method.


Usage — Running the Generators

From vRO (recommended)

  1. Aria Assembler → Extensibility → Workflows
  2. Pick "Generate Ansible Inventory from vSphere" or "Generate Ansible Inventory from OneView"
  3. Click Run
  4. Fill in the form (vCenter/OneView host, credentials, options)
  5. Submit — watch the logs in the Workflow Run tab
  6. Output: inventory file path + log file path

From the command line (bypass vRO)

vSphere:

ssh ansible@ansible.example.com
cd /home/ansible/inventories/vsphere
python3.11 generate_vsphere_inventory.py \
  --vcenter-host vcenter-tx01.example.com \
  --vcenter-user administrator@vsphere.local \
  --vcenter-password '<pw>' \
  --environment prod \
  --skip-templates \
  --require-ip

OneView:

ssh ansible@ansible.example.com
cd /home/ansible/inventories/oneview
python3 generate_oneview_inventory.py \
  --oneview-host oneview-tx01.example.com \
  --oneview-user Administrator \
  --oneview-password '<pw>' \
  --version 8.9 \
  --local-account

Troubleshooting

vRO workflow fails at "Connecting to Ansible server"

SSH can't reach the control node or the password is wrong. Check:

  1. Network path from vRO appliance → ansible.example.com (TCP 22)
  2. ansible user password in the workflow form matches the current password on the control node
  3. SSH daemon is running: sshd -t on the control node

Python script exits with "certificate verify failed"

Default behavior is to skip cert validation (--validate-certs is off by default on the vSphere script). If you've re-enabled it and hit this, the vCenter or OneView cert isn't in the control node's trust store. Either trust the cert or disable validation.

OneView returns 401 Unauthorized

Wrong X-API-Version for the connected OneView. Double-check the --version value against the actual appliance version:

curl -sk https://<oneview>/rest/version | python3 -m json.tool

Match the appliance's currentVersion to the table in this README.

Inventory file is empty

The source system has no matching objects, or filters are too strict. Remove --require-ip and --skip-powered-off to widen the net and see what's actually being discovered.

Bitbucket push fails with 401 or 403

Token is wrong, expired, or lacks write access. Generate a new token in Bitbucket → Personal settings → App passwords with Repositories: Read, Write scope. Update the vRO workflow's bitbucketToken input to the new value.

"Inventory file already exists" or commit is a no-op

The generator produced an inventory identical to the last commit. This is safe — the push script handles it with changesPushed: false in the output. No action needed.

vSphere inventory missing powered-off VMs

By default the script includes them. If missing, check: was --skip-powered-off passed? Also, powered-off VMs without a cached guest IP get filtered out if --require-ip is set.


Version Summary

Artifact Lines Notes
Create-ansible-inventory-from-vSphere.py 616 Full vSphere inventory generator with IP/folder/OS grouping
Get-all-VMs-from-vCenter.js 133 vRO scriptable task; hardcoded ansible host + script path
push_inventory_to_bitbucket.js 233 vRO scriptable task; token-based git push
generate_oneview_inventory.py 682 Supports OneView 6.6 / 8.9 / 10.0 via API version mapping
vro_workflow.js 245 Single scriptable task for OneView workflow
ansible_inventory_generators.package Signed vRO package containing both workflows

All scripts were validated byte-identical between the desktop working copies and the signed customer vRO package export (see validation notes in the closeout chat).


Contact

Original author: Noah Farshad (noah@essential.coach) Engagement: VMware / Aria Automation reference implementation

About

Python inventory generators for VMware vSphere and HPE OneView (6.6 / 8.9 / 10.0), triggered via vRealize Orchestrator workflows. Produces INI-format Ansible inventories grouped by OS, folder, and environment

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors