Skip to content

feat(vm-consumption-report): add VM consumption reporting role#7

Closed
stevefulme1 wants to merge 15 commits into
redhat-cop:mainfrom
stevefulme1:feat/vm-consumption-report
Closed

feat(vm-consumption-report): add VM consumption reporting role#7
stevefulme1 wants to merge 15 commits into
redhat-cop:mainfrom
stevefulme1:feat/vm-consumption-report

Conversation

@stevefulme1

Copy link
Copy Markdown
Contributor

Summary

  • Adds vm_consumption_report role and playbook for generating consumption reports of OpenShift Virtualization VMs
  • Queries VirtualMachine and VirtualMachineInstance resources via kubernetes.core.k8s_info, supporting namespace and label selector filtering
  • Reconciles directly managed hosts (SSH/WinRM) with API-managed VMs via UUID, guest hostname, and IP address matching
  • Outputs reports in JSON or CSV format with summary counts (indirect, direct, reconciled)

Moved from

Originally submitted as redhat-cop/openshift_virtualization_migration#29 — relocated here as this is day 2 ops functionality (reporting/inventory of running VMs), not migration logic.

FQCN updated from infra.openshift_virtualization_migration to infra.openshift_virtualization_ops.

Test plan

  • Verify yamllint passes
  • Verify ansible-lint --offline passes production profile
  • Run playbook against an OpenShift cluster with KubeVirt VMs
  • Verify JSON output includes correct VM entries and summary counts
  • Verify CSV output renders correctly
  • Test reconciliation with vm_consumption_report_direct_hosts entries
  • Test with vm_consumption_report_include_status: false to skip VMI queries

🤖 Generated with Claude Code

Move from openshift_virtualization_migration repo — this is day 2 ops
functionality for generating consumption reports of running OCP VMs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add filename prefix to task names in _collect_vms.yml, _collect_vmis.yml,
and _build_report.yml to satisfy ansible-lint name[prefix] rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@sabre1041 sabre1041 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevefulme1 Reviewed the report generation. There are some questions that I have based on this integration.

  1. See the additional filter for removing null values in the lastTransitionTime property
  2. The reconciled field will never contain a positive value as a match is not possible
  3. Is the goal to have a set of hostnames/uuid's and check if a match is found in the cluster?

last_transition: >-
{{ _vm.status.conditions
| default([])
| sort(attribute='lastTransitionTime')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| sort(attribute='lastTransitionTime')
| selectattr('lastTransitionTime', 'defined') | rejectattr('lastTransitionTime', 'none')
| sort(attribute='lastTransitionTime')

Need to filter out items that contain null values

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — pushed this fix in 89241f3. Added selectattr('lastTransitionTime', 'defined') | rejectattr('lastTransitionTime', 'none') before the sort.

| list | first | default({}) }}
_vm_uuid: "{{ _vm.metadata.uid }}"
_guest_hostname: >-
{{ _vmi_match.status.guestOSInfo.hostname | default('') }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hostname is not a valid field for guestOSInfo so we will never have a reconcile entry

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right — guestOSInfo doesn't expose a hostname field. The guest agent hostname isn't available at that path in the VMI status.

The reconciliation still works via UUID and IP address matching, but the hostname branch of _direct_match is effectively dead code. I'll remove guestOSInfo.hostname as a matching source. If there's a different VMI status path you'd recommend for guest hostname, happy to wire that in instead.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Targeting a VMI for reporting purposes is risky as no instance is created when a VM is not running.

There are a few options for looking into capturing VM information. It is not exposed in the status field, but you can check the .spec.template.spec.hostname field to see if it has been explicitly defined and maybe just fallback to metadata.name as that is used by default

Conditions with undefined or null lastTransitionTime values cause
sort(attribute='lastTransitionTime') to fail. Filter them out with
selectattr/rejectattr before sorting.
guestOSInfo does not expose a hostname field. Set _guest_hostname
to empty string, disabling hostname-based reconciliation. UUID and
IP address matching remain functional.
@stevefulme1

Copy link
Copy Markdown
Contributor Author

Addressing the review:

  1. Null lastTransitionTime filter — Fixed in 89241f3. Added selectattr('lastTransitionTime', 'defined') | rejectattr('lastTransitionTime', 'none') before the sort.

  2. guestOSInfo.hostname doesn't exist — Fixed in 6b84fa5. Removed the invalid field reference. _guest_hostname is now set to empty string, which disables the hostname branch of _direct_match. Reconciliation still works via UUID and IP address matching. If there's a valid VMI status path for guest hostname I'm not aware of, happy to wire it back in.

  3. Goal of the reconciliation — Yes, the intent is to take a list of known hosts (from AAP inventory or a static list via vm_consumption_report_direct_hosts) and check which ones have a matching VM in the cluster. Matches are tagged reconciled, cluster VMs with no match are indirect, and inventory hosts with no cluster VM are direct_only. This gives a consumption report showing which VMs are managed by AAP vs. discovered on the cluster without a corresponding inventory entry.

Use .spec.template.spec.hostname from the VM object with fallback
to metadata.name rather than relying on VMI guestOSInfo. VMI does
not exist when a VM is stopped, making it unreliable for reporting.
@burigolucas burigolucas deployed to external-ci May 18, 2026 12:45 — with GitHub Actions Active
@stevefulme1 stevefulme1 deleted the feat/vm-consumption-report branch May 18, 2026 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants