From 38b134814ab768c19095ddd513752ef431b2b3d7 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 19 Feb 2026 08:24:31 +0100 Subject: [PATCH 1/3] fix: update volume metadata when skipping V2V conversion When skip_conversion is true (useful for appliances or OSes not recognized by virt-v2v), the disk copy was completing correctly but the Cinder volume metadata was never updated to converted=true. Ansible reads this metadata to decide whether to create the instance, so it was silently skipping instance creation after a successful copy. This adds the same metadata update that exists in the normal V2V path. --- plugins/modules/src/migrate/migrate.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/modules/src/migrate/migrate.go b/plugins/modules/src/migrate/migrate.go index f12500b5..e951976a 100644 --- a/plugins/modules/src/migrate/migrate.go +++ b/plugins/modules/src/migrate/migrate.go @@ -382,6 +382,14 @@ func (c *MigrationConfig) VMMigration(parentCtx context.Context, runV2V bool) (s } } else { logger.Log.Infof("Skipping V2V conversion...") + volMetadata = map[string]string{ + "osm": "true", + "converted": "true", + } + err = osm_os.UpdateVolumeMetadata(c.OSClient, volume.ID, volMetadata) + if err != nil { + logger.Log.Infof("Failed to set volume metadata: %v, ignoring ...", err) + } } } } From 301e5f5b8112f17993106766813bdd1231f09e98 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 4 Mar 2026 06:46:52 +0100 Subject: [PATCH 2/3] fix: use osm_state:ready instead of converted:true when skipping V2V --- plugins/modules/src/migrate/migrate.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/plugins/modules/src/migrate/migrate.go b/plugins/modules/src/migrate/migrate.go index b586d982..962bd283 100644 --- a/plugins/modules/src/migrate/migrate.go +++ b/plugins/modules/src/migrate/migrate.go @@ -159,6 +159,10 @@ func (c *MigrationConfig) VMMigration(parentCtx context.Context, runV2V bool) (s logger.Log.Infof("Volume already converted, skipping migration..") return volume.ID, nil } + if state, ok := volume.Metadata["osm_state"]; ok && state == "ready" { + logger.Log.Infof("Volume already migrated and ready to be used by OpenStack, skipping...") + return volume.ID, nil + } if c.CBTSync { logger.Log.Infof("Volume exists, syncing volume..") syncVol = true @@ -381,11 +385,11 @@ func (c *MigrationConfig) VMMigration(parentCtx context.Context, runV2V bool) (s logger.Log.Infof("Failed to set volume metadata: %v, ignoring ...", err) } } else { - logger.Log.Infof("Skipping V2V conversion...") - volMetadata = map[string]string{ - "osm": "true", - "converted": "true", - } + logger.Log.Infof("Skipping V2V conversion...") + volMetadata = map[string]string{ + "osm": "true", + "osm_state": "ready", + } err = osm_os.UpdateVolumeMetadata(c.OSClient, volume.ID, volMetadata) if err != nil { logger.Log.Infof("Failed to set volume metadata: %v, ignoring ...", err) From 3c16a58b2f5c2f4dd38c4d5da0b56778c577d3ea Mon Sep 17 00:00:00 2001 From: root Date: Wed, 4 Mar 2026 09:08:04 +0100 Subject: [PATCH 3/3] fix: check osm_state:ready in volume_metadata_info to unblock instance creation --- plugins/module_utils/openstack/openstack.go | 17 +++++++++++++++++ .../volume_metadata_info.go | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/plugins/module_utils/openstack/openstack.go b/plugins/module_utils/openstack/openstack.go index ca3aa9cb..a0165b5c 100644 --- a/plugins/module_utils/openstack/openstack.go +++ b/plugins/module_utils/openstack/openstack.go @@ -241,6 +241,23 @@ func IsVolumeConverted(client *gophercloud.ProviderClient, volumeID string) (boo return false, nil } +func IsVolumeReady(client *gophercloud.ProviderClient, volumeID string) (bool, error) { + blockStorageClient, err := openstack.NewBlockStorageV3(client, gophercloud.EndpointOpts{}) + if err != nil { + logger.Log.Infof("Failed to create block storage client: %v", err) + return false, err + } + volume, err := volumes.Get(context.TODO(), blockStorageClient, volumeID).Extract() + if err != nil { + logger.Log.Infof("Failed to get volume: %v", err) + return false, err + } + if state, ok := volume.Metadata["osm_state"]; ok { + return state == "ready", nil + } + return false, nil +} + func GetOSChangeID(client *gophercloud.ProviderClient, volumeID string) (string, error) { blockStorageClient, err := openstack.NewBlockStorageV3(client, gophercloud.EndpointOpts{}) if err != nil { diff --git a/plugins/modules/src/volume_metadata_info/volume_metadata_info.go b/plugins/modules/src/volume_metadata_info/volume_metadata_info.go index 7a1c3da4..5ea583de 100644 --- a/plugins/modules/src/volume_metadata_info/volume_metadata_info.go +++ b/plugins/modules/src/volume_metadata_info/volume_metadata_info.go @@ -99,6 +99,13 @@ func main() { response.Msg = "Failed to get volume metadata: " + moduleArgs.VolumeID + " error: " + err.Error() FailJson(response) } + if !converted { + converted, err = osm_os.IsVolumeReady(provider, moduleArgs.VolumeID) + if err != nil { + response.Msg = "Failed to get volume state: " + moduleArgs.VolumeID + " error: " + err.Error() + FailJson(response) + } + } response.Changed = true response.Msg = "Volume metadata info" response.Converted = converted