Skip to content

ECOPROJECT-4285 | feat: add datastore storage io information into the api#1184

Open
itroyano wants to merge 1 commit into
kubev2v:mainfrom
itroyano:ECOPROJECT-4285
Open

ECOPROJECT-4285 | feat: add datastore storage io information into the api#1184
itroyano wants to merge 1 commit into
kubev2v:mainfrom
itroyano:ECOPROJECT-4285

Conversation

@itroyano
Copy link
Copy Markdown
Contributor

@itroyano itroyano commented May 18, 2026

Signed-off-by: Igor Troyanovsky itroyano@redhat.com

rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED

Assisted-by: Claude Opus 4.6

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for Storage I/O Control configuration on datastores, including enablement status, congestion threshold settings, threshold mode (automatic or manual), and peak throughput controls.
  • Tests

    • Added comprehensive test coverage for Storage I/O Control configuration validation and parsing, including default fallback behavior when configuration data is unavailable.

Review Change Stack

… api

Signed-off-by: Igor Troyanovsky <itroyano@redhat.com>

rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
@itroyano itroyano requested a review from a team as a code owner May 18, 2026 15:11
@itroyano itroyano requested review from amalimov and nirarg and removed request for a team May 18, 2026 15:11
@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 18, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign ammont82 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

📝 Walkthrough

Walkthrough

This PR adds Storage I/O Control (SIOC) configuration support to the migration planner. It extends the API schema and data models, updates database ingestion pipelines to parse SIOC properties from source systems, implements queries with sensible defaults, constructs inventory objects, and validates the end-to-end flow with comprehensive tests.

Changes

Storage I/O Control Configuration Support

Layer / File(s) Summary
API contract and schema definition
api/v1alpha1/openapi.yaml, api/v1alpha1/types.gen.go, api/v1alpha1/agent/spec.gen.go, api/v1alpha1/spec.gen.go
OpenAPI schema and generated Go types define new StorageIoConfiguration struct with enabled, congestionThreshold, congestionThresholdMode (enum: automatic/manual), and percentOfPeakThroughput fields; Datastore schema extended with optional storageIoConfiguration reference.
Database model and schema
pkg/inventory/model.go, pkg/duckdb_parser/models/inventory.go, pkg/duckdb_parser/templates/create_schema.go.tmpl
Internal Datastore model and vdatastore table schema extended with SIOC fields: SiocEnabled, SiocCongestionThreshold, SiocCongestionThresholdMode, and SiocPercentOfPeakThroughput.
Data ingestion from source systems
pkg/duckdb_parser/templates/ingest_rvtools.go.tmpl, pkg/duckdb_parser/templates/ingest_sqlite.go.tmpl
RVTools and SQLite ingest pipelines parse SIOC columns from source data, applying type conversions and defaults (false, 30, automatic, 90 respectively).
Query and retrieval with defaults
pkg/duckdb_parser/templates/datastore_query.go.tmpl
Datastore queries select SIOC fields from vdatastore through clustered and vCenter-level paths, propagating values through intermediate CTEs and applying COALESCE defaults in final SELECT statements.
Inventory construction and API mapping
pkg/duckdb_parser/inventory_builder.go, pkg/inventory/converters/to_api.go
Inventory builder constructs StorageIoConfiguration objects from datastore fields; API converter conditionally maps internal configuration to API response types with enum conversion for congestion threshold mode.
End-to-end testing and validation
pkg/duckdb_parser/inventory_builder_test.go
Test scaffolding extended with SIOC headers and row data; new TestBuildInventory_StorageIoConfiguration test validates explicit SIOC column ingestion and default-when-missing behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

ok-to-test

Suggested reviewers

  • nirarg
  • AvielSegev

Poem

A rabbit hops through schemas bright,
With Storage I/O Control in sight,
From Excel sheets to queries deep,
The SIOC defaults, safely keep,
Through layers mapped, the data flows right! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding datastore storage I/O (SIOC) configuration support throughout the API and internal models.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/duckdb_parser/templates/datastore_query.go.tmpl (1)

46-63: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix non-deterministic HBA type derivation using proper aggregation.

Line 56 uses FIRST(hba."Type") OVER (PARTITION BY w."Name") without an ORDER BY clause. DuckDB's FIRST() function is non-deterministic without explicit ordering, producing unstable or NULL values that incorrectly classify protocolType in the final query (line 74). Replace the window function with deterministic aggregation using GROUP BY.

Suggested fix
 with_hba AS (
-    SELECT DISTINCT
+    SELECT
         w."Cluster",
         w."Address",
         w."Name",
         w."Free MiB",
         w."MHA",
         w."Capacity MiB",
         w."Type",
         w.ip,
         w."Object ID",
-        FIRST(hba."Type") OVER (PARTITION BY w."Name") as hba_type,
+        MAX(hba."Type") FILTER (WHERE hba."Type" IS NOT NULL) as hba_type,
         w."SIOC Enabled",
         w."SIOC Congestion Threshold",
         w."SIOC Congestion Threshold Mode",
         w."SIOC Percent Of Peak Throughput"
     FROM with_host w
     LEFT JOIN vhba hba ON hba."Device" = w.hba_device
+    GROUP BY
+        w."Cluster", w."Address", w."Name", w."Free MiB", w."MHA", w."Capacity MiB",
+        w."Type", w.ip, w."Object ID",
+        w."SIOC Enabled", w."SIOC Congestion Threshold",
+        w."SIOC Congestion Threshold Mode", w."SIOC Percent Of Peak Throughput"
 )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/duckdb_parser/templates/datastore_query.go.tmpl` around lines 46 - 63,
The SELECT uses FIRST(hba."Type") OVER (PARTITION BY w."Name") (aliased as
hba_type) which is non-deterministic without ORDER BY; replace this windowed
FIRST with a deterministic aggregate and GROUP BY: remove the window function,
add hba_type as an aggregate (e.g., MAX(hba."Type") or MIN(...) depending on
desired precedence) and GROUP BY all non-aggregated w.* columns from the
with_host row (w."Cluster", w."Address", w."Name", w."Free MiB", w."MHA",
w."Capacity MiB", w."Type", w.ip, w."Object ID", and the SIOC fields) so that
hba_type is computed deterministically from the LEFT JOIN to vhba.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/duckdb_parser/templates/ingest_rvtools.go.tmpl`:
- Line 247: The template currently passes any non-empty "SIOC Congestion
Threshold Mode" through, which can produce values outside the API enum; replace
the COALESCE(NULLIF(TRIM("SIOC Congestion Threshold Mode"), ''), 'automatic')
expression with a normalization that lowercases and constrains values to either
'manual' or 'automatic' (e.g., use a CASE on LOWER(TRIM("SIOC Congestion
Threshold Mode")) returning 'manual' when it equals 'manual' and 'automatic'
otherwise) so the generated column always yields one of the API enum values.

In `@pkg/inventory/converters/to_api.go`:
- Around line 205-213: The StorageIoConfiguration block creates pointers to
fields of d.StorageIoConfiguration directly which is unsafe; extract each value
into local variables first (e.g., enabled := d.StorageIoConfiguration.Enabled,
congestion := d.StorageIoConfiguration.CongestionThreshold, percent :=
d.StorageIoConfiguration.PercentOfPeakThroughput and mode :=
api.StorageIoConfigurationCongestionThresholdMode(d.StorageIoConfiguration.CongestionThresholdMode))
and then assign &enabled, &congestion, &mode, &percent when building
ds.StorageIoConfiguration so pointers reference stable local variables instead
of fields directly.

---

Outside diff comments:
In `@pkg/duckdb_parser/templates/datastore_query.go.tmpl`:
- Around line 46-63: The SELECT uses FIRST(hba."Type") OVER (PARTITION BY
w."Name") (aliased as hba_type) which is non-deterministic without ORDER BY;
replace this windowed FIRST with a deterministic aggregate and GROUP BY: remove
the window function, add hba_type as an aggregate (e.g., MAX(hba."Type") or
MIN(...) depending on desired precedence) and GROUP BY all non-aggregated w.*
columns from the with_host row (w."Cluster", w."Address", w."Name", w."Free
MiB", w."MHA", w."Capacity MiB", w."Type", w.ip, w."Object ID", and the SIOC
fields) so that hba_type is computed deterministically from the LEFT JOIN to
vhba.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 99f470f9-6f9c-40ab-bc6e-7955923362e9

📥 Commits

Reviewing files that changed from the base of the PR and between eddc84b and 1fdd133.

📒 Files selected for processing (13)
  • api/v1alpha1/agent/spec.gen.go
  • api/v1alpha1/openapi.yaml
  • api/v1alpha1/spec.gen.go
  • api/v1alpha1/types.gen.go
  • pkg/duckdb_parser/inventory_builder.go
  • pkg/duckdb_parser/inventory_builder_test.go
  • pkg/duckdb_parser/models/inventory.go
  • pkg/duckdb_parser/templates/create_schema.go.tmpl
  • pkg/duckdb_parser/templates/datastore_query.go.tmpl
  • pkg/duckdb_parser/templates/ingest_rvtools.go.tmpl
  • pkg/duckdb_parser/templates/ingest_sqlite.go.tmpl
  • pkg/inventory/converters/to_api.go
  • pkg/inventory/model.go

"Type",
CASE WHEN LOWER(TRIM(COALESCE("SIOC Enabled", ''))) IN ('true', '1', 'yes') THEN true ELSE false END,
COALESCE(TRY_CAST("SIOC Congestion Threshold" AS INTEGER), 30),
COALESCE(NULLIF(TRIM("SIOC Congestion Threshold Mode"), ''), 'automatic'),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Normalize and constrain SIOC mode to the API enum values.

Line 247 passes any non-empty value through. That can emit values outside automatic|manual (including case variants), breaking the API contract.

Suggested fix
-    COALESCE(NULLIF(TRIM("SIOC Congestion Threshold Mode"), ''), 'automatic'),
+    CASE
+      WHEN LOWER(TRIM(COALESCE("SIOC Congestion Threshold Mode", ''))) IN ('automatic', 'manual')
+        THEN LOWER(TRIM("SIOC Congestion Threshold Mode"))
+      ELSE 'automatic'
+    END,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
COALESCE(NULLIF(TRIM("SIOC Congestion Threshold Mode"), ''), 'automatic'),
CASE
WHEN LOWER(TRIM(COALESCE("SIOC Congestion Threshold Mode", ''))) IN ('automatic', 'manual')
THEN LOWER(TRIM("SIOC Congestion Threshold Mode"))
ELSE 'automatic'
END,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/duckdb_parser/templates/ingest_rvtools.go.tmpl` at line 247, The template
currently passes any non-empty "SIOC Congestion Threshold Mode" through, which
can produce values outside the API enum; replace the COALESCE(NULLIF(TRIM("SIOC
Congestion Threshold Mode"), ''), 'automatic') expression with a normalization
that lowercases and constrains values to either 'manual' or 'automatic' (e.g.,
use a CASE on LOWER(TRIM("SIOC Congestion Threshold Mode")) returning 'manual'
when it equals 'manual' and 'automatic' otherwise) so the generated column
always yields one of the API enum values.

Comment on lines +205 to +213
if d.StorageIoConfiguration != nil {
mode := api.StorageIoConfigurationCongestionThresholdMode(d.StorageIoConfiguration.CongestionThresholdMode)
ds.StorageIoConfiguration = &api.StorageIoConfiguration{
Enabled: &d.StorageIoConfiguration.Enabled,
CongestionThreshold: &d.StorageIoConfiguration.CongestionThreshold,
CongestionThresholdMode: &mode,
PercentOfPeakThroughput: &d.StorageIoConfiguration.PercentOfPeakThroughput,
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify pointer aliasing pattern in converter mapping.
rg -n '(&d\.StorageIoConfiguration\.)|(StorageIoConfiguration:\s*&api\.StorageIoConfiguration)' pkg/inventory/converters/to_api.go

Repository: kubev2v/migration-planner

Length of output: 301


🏁 Script executed:

# Get the full function context around lines 205-213
sed -n '190,220p' pkg/inventory/converters/to_api.go

Repository: kubev2v/migration-planner

Length of output: 1223


🏁 Script executed:

# Check the function signature and parameter types
head -n 250 pkg/inventory/converters/to_api.go | tail -n 100

Repository: kubev2v/migration-planner

Length of output: 2908


🏁 Script executed:

# Search for similar aliasing patterns in the same converter file
rg -n '&d\.' pkg/inventory/converters/to_api.go | head -20

Repository: kubev2v/migration-planner

Length of output: 365


🏁 Script executed:

# Look for related tests for this converter function
find . -name '*to_api*test*.go' -o -name '*converter*test*.go' | grep -E 'inventory|converter'

Repository: kubev2v/migration-planner

Length of output: 111


🏁 Script executed:

# View the test file to understand coverage and patterns
head -n 100 pkg/inventory/converters/to_api_test.go

Repository: kubev2v/migration-planner

Length of output: 2642


🏁 Script executed:

# Find type definitions for StorageIoConfiguration in inventory package
find pkg/inventory -name '*.go' | xargs grep -l 'type StorageIoConfiguration' | head -5

Repository: kubev2v/migration-planner

Length of output: 92


🏁 Script executed:

# Look for the complete type definition
rg -A 10 'type StorageIoConfiguration struct' pkg/inventory

Repository: kubev2v/migration-planner

Length of output: 613


🏁 Script executed:

# Search for usage of the toAPIInfra function result
rg -B 3 -A 3 'toAPIInfra' pkg/inventory/converters/to_api.go

Repository: kubev2v/migration-planner

Length of output: 386


🏁 Script executed:

# Check the return type and how it's propagated
rg -A 5 'func ToAPI' pkg/inventory/converters/to_api.go | head -20

Repository: kubev2v/migration-planner

Length of output: 270


🏁 Script executed:

# Search for concurrent access patterns or channel usage with API structs
rg -n 'go ' pkg/inventory/converters/to_api.go

Repository: kubev2v/migration-planner

Length of output: 51


🏁 Script executed:

# Check if the Datastore or API objects are modified after conversion
rg -n 'StorageIoConfiguration' pkg/inventory/converters/ --type go

Repository: kubev2v/migration-planner

Length of output: 733


Extract values to local variables before taking addresses for StorageIoConfiguration fields.

This block directly addresses fields from the source struct, inconsistent with the safe pattern used elsewhere in this same function (e.g., lines 212–214 for HostId, lines 217–225 for host CPU/memory fields). Extract the values to locals first, then take addresses of the locals.

Suggested fix
 		if d.StorageIoConfiguration != nil {
+			enabled := d.StorageIoConfiguration.Enabled
+			congestionThreshold := d.StorageIoConfiguration.CongestionThreshold
 			mode := api.StorageIoConfigurationCongestionThresholdMode(d.StorageIoConfiguration.CongestionThresholdMode)
+			percentOfPeakThroughput := d.StorageIoConfiguration.PercentOfPeakThroughput
 			ds.StorageIoConfiguration = &api.StorageIoConfiguration{
-				Enabled:                 &d.StorageIoConfiguration.Enabled,
-				CongestionThreshold:     &d.StorageIoConfiguration.CongestionThreshold,
+				Enabled:                 &enabled,
+				CongestionThreshold:     &congestionThreshold,
 				CongestionThresholdMode: &mode,
-				PercentOfPeakThroughput: &d.StorageIoConfiguration.PercentOfPeakThroughput,
+				PercentOfPeakThroughput: &percentOfPeakThroughput,
 			}
 		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if d.StorageIoConfiguration != nil {
mode := api.StorageIoConfigurationCongestionThresholdMode(d.StorageIoConfiguration.CongestionThresholdMode)
ds.StorageIoConfiguration = &api.StorageIoConfiguration{
Enabled: &d.StorageIoConfiguration.Enabled,
CongestionThreshold: &d.StorageIoConfiguration.CongestionThreshold,
CongestionThresholdMode: &mode,
PercentOfPeakThroughput: &d.StorageIoConfiguration.PercentOfPeakThroughput,
}
}
if d.StorageIoConfiguration != nil {
enabled := d.StorageIoConfiguration.Enabled
congestionThreshold := d.StorageIoConfiguration.CongestionThreshold
mode := api.StorageIoConfigurationCongestionThresholdMode(d.StorageIoConfiguration.CongestionThresholdMode)
percentOfPeakThroughput := d.StorageIoConfiguration.PercentOfPeakThroughput
ds.StorageIoConfiguration = &api.StorageIoConfiguration{
Enabled: &enabled,
CongestionThreshold: &congestionThreshold,
CongestionThresholdMode: &mode,
PercentOfPeakThroughput: &percentOfPeakThroughput,
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/inventory/converters/to_api.go` around lines 205 - 213, The
StorageIoConfiguration block creates pointers to fields of
d.StorageIoConfiguration directly which is unsafe; extract each value into local
variables first (e.g., enabled := d.StorageIoConfiguration.Enabled, congestion
:= d.StorageIoConfiguration.CongestionThreshold, percent :=
d.StorageIoConfiguration.PercentOfPeakThroughput and mode :=
api.StorageIoConfigurationCongestionThresholdMode(d.StorageIoConfiguration.CongestionThresholdMode))
and then assign &enabled, &congestion, &mode, &percent when building
ds.StorageIoConfiguration so pointers reference stable local variables instead
of fields directly.

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.

1 participant