From c02d86aa896763a05b9a37e89e67b0d101da01ec Mon Sep 17 00:00:00 2001 From: root Date: Thu, 26 Feb 2026 06:41:28 +0100 Subject: [PATCH 1/2] feat: support vm_dest_name for OpenStack resource naming Allow specifying an optional destination name (vm_dest_name) for a VM being migrated. When provided, it is used instead of the VMware VM name when naming OpenStack resources (Cinder volumes, Nova instance, Neutron ports). The original vm_name continues to be used to locate the VM in vCenter. This is useful when the target name in OpenStack must differ from the source name in VMware, for example to apply a naming convention or to avoid conflicts. --- .../run_migration_from_conversion_host.yml | 1 + .../create_network_port.go | 9 +++++- .../src/create_server/create_server.go | 16 ++++++++-- plugins/modules/src/migrate/migrate.go | 30 +++++++++++++++++-- roles/convert_metadata/tasks/main.yml | 1 + .../templates/import_workloads.json.j2 | 1 + .../tasks/create_network_port.yml | 3 ++ .../tasks/create_os_instance.yml | 5 ++-- roles/import_workloads/tasks/nbdkit.yml | 1 + 9 files changed, 59 insertions(+), 8 deletions(-) diff --git a/playbooks/run_migration_from_conversion_host.yml b/playbooks/run_migration_from_conversion_host.yml index a655833a..b8c8cdad 100644 --- a/playbooks/run_migration_from_conversion_host.yml +++ b/playbooks/run_migration_from_conversion_host.yml @@ -27,3 +27,4 @@ vars: flavor_name_or_uuid: "{{ data.openstack.flavor_name_or_uuid }}" vm_name: "{{ data.vm_name }}" + vm_dest_name: "{{ data.vm_dest_name | default('') }}" diff --git a/plugins/modules/src/create_network_port/create_network_port.go b/plugins/modules/src/create_network_port/create_network_port.go index e79e959f..367c20fa 100644 --- a/plugins/modules/src/create_network_port/create_network_port.go +++ b/plugins/modules/src/create_network_port/create_network_port.go @@ -31,6 +31,9 @@ type ModuleArgs struct { Cloud osm_os.DstCloud `json:"cloud"` OsMigrateNicsFilePath string `json:"os_migrate_nics_file_path"` VmName string `json:"vm_name"` + // DestName is an optional override for port naming. + // When provided it is used instead of SafeVmName(VmName). + DestName string `json:"destname"` UsedMappedNetworks bool `json:"used_mapped_networks"` SecurityGroups []string `json:"security_groups"` NetworkName string `json:"network_name"` @@ -181,7 +184,11 @@ func main() { } } } - portName := fmt.Sprintf("%s-NIC-%d-VLAN-%s", moduleArgs.VmName, nicIndex, nic.Vlan) + portBaseName := moduleArgs.VmName + if moduleArgs.DestName != "" { + portBaseName = moduleArgs.DestName + } + portName := fmt.Sprintf("%s-NIC-%d-VLAN-%s", portBaseName, nicIndex, nic.Vlan) port, err := osm_os.CreatePort(provider, portName, network.ID, nic.Mac, nic.Subnet, moduleArgs.SecurityGroups, nic.FixedIPs) if err != nil { diff --git a/plugins/modules/src/create_server/create_server.go b/plugins/modules/src/create_server/create_server.go index 44e65dbd..9b166dd1 100644 --- a/plugins/modules/src/create_server/create_server.go +++ b/plugins/modules/src/create_server/create_server.go @@ -62,6 +62,10 @@ type ModuleArgs struct { Cloud osm_os.DstCloud `json:"cloud"` State string `json:"state"` Name string `json:"name"` + // DestName is an optional override for the OpenStack instance name. + // When provided it is used as-is, bypassing SafeVmName sanitisation. + // When absent, SafeVmName(Name) is used (default behaviour). + DestName string `json:"destname"` Nics []interface{} `json:"nics"` BootVolume string `json:"boot_volume"` Volumes []string `json:"volumes"` @@ -80,6 +84,14 @@ type ModuleResponse struct { ID string `json:"id"` } +// resolveInstanceName returns DestName if set, otherwise SafeVmName(Name). +func resolveInstanceName(args ModuleArgs) string { + if args.DestName != "" { + return args.DestName + } + return moduleutils.SafeVmName(args.Name) +} + func success(changed bool, id string) { res := ModuleResponse{ Changed: changed, @@ -153,7 +165,7 @@ func main() { } ServerAgrs := osm_os.ServerArgs{ - Name: moduleArgs.Name, + Name: resolveInstanceName(moduleArgs), Flavor: moduleArgs.Flavor, BootVolume: moduleArgs.BootVolume, SecurityGroups: moduleArgs.SecurityGroups, @@ -172,7 +184,7 @@ func main() { } ServerAgrs := osm_os.ServerArgs{ - Name: moduleArgs.Name, + Name: resolveInstanceName(moduleArgs), Flavor: moduleArgs.Flavor, BootVolume: moduleArgs.BootVolume, SecurityGroups: moduleArgs.SecurityGroups, diff --git a/plugins/modules/src/migrate/migrate.go b/plugins/modules/src/migrate/migrate.go index f12500b5..8ac45720 100644 --- a/plugins/modules/src/migrate/migrate.go +++ b/plugins/modules/src/migrate/migrate.go @@ -69,6 +69,9 @@ type MigrationConfig struct { Server string Libdir string VmName string + // DestName is the optional destination name used for Cinder volume naming. + // If empty, SafeVmName(VmName) is used instead (default behaviour). + DestName string VolumeAz string VolumeType string AssumeZero bool @@ -104,6 +107,10 @@ type ModuleArgs struct { Server string Libdir string VmName string + // DestName is the optional destination name used for Cinder volume naming. + // When provided, it replaces SafeVmName(VmName) for resource naming while + // VmName continues to be used to locate the VM in vCenter. + DestName string `json:"destname"` VolumeAz string VolumeType string VolumeTypeMapping []VolumeTypeMapping `json:"volume_type_mapping"` @@ -127,6 +134,16 @@ type ModuleArgs struct { ExtraOpts string } +// resourceName returns the name to use when creating OpenStack resources +// (Cinder volumes). If DestName is set it is used as-is; otherwise the +// VMware VM name is sanitised with SafeVmName. +func (c *MigrationConfig) resourceName(vmName string) string { + if c.DestName != "" { + return c.DestName + } + return moduleutils.SafeVmName(vmName) +} + func (c *MigrationConfig) VMMigration(parentCtx context.Context, runV2V bool) (string, error) { syncVol := false ctx, cancel := context.WithCancel(context.Background()) @@ -144,7 +161,7 @@ func (c *MigrationConfig) VMMigration(parentCtx context.Context, runV2V bool) (s return "", err } diskNameStr := strconv.Itoa(int(c.NbdkitConfig.VddkConfig.DiskKey)) - volume, err := osm_os.GetVolumeID(c.OSClient, vmName, diskNameStr) + volume, err := osm_os.GetVolumeID(c.OSClient, c.resourceName(vmName), diskNameStr) if err != nil { logger.Log.Infof("Failed to get volume: %v", err) return "", err @@ -223,7 +240,7 @@ func (c *MigrationConfig) VMMigration(parentCtx context.Context, runV2V bool) (s // volumeMetadata["hw_scsi_model"] = "virtio-scsi" // } volOpts := osm_os.VolOpts{ - Name: vmName + "-" + diskNameStr, + Name: c.resourceName(vmName) + "-" + diskNameStr, Size: int(diskSize[diskNameStr] / 1024 / 1024), VolumeType: c.VolumeType, AvailabilityZone: c.VolumeAz, @@ -418,6 +435,7 @@ func main() { password := ansible.RequireField(moduleArgs.Password, "Password is required") server := ansible.RequireField(moduleArgs.Server, "Server is required") vmname := ansible.RequireField(moduleArgs.VmName, "VM name is required") + destname := moduleArgs.DestName libdir := ansible.DefaultIfEmpty(moduleArgs.Libdir, "/usr/lib/vmware-vix-disklib") vddkpath := ansible.DefaultIfEmpty(moduleArgs.VddkPath, "/ha-datacenter/vm/") osmdatadir := ansible.DefaultIfEmpty(moduleArgs.OSMDataDir, "/tmp/") @@ -447,8 +465,13 @@ func main() { response.Msg = "Failed to generate random string" ansible.FailJson(response) } + // Use destname for the log file name if provided, otherwise use the sanitised VM name safeVmName := moduleutils.SafeVmName(vmname) - LogFile := "/tmp/osm-nbdkit-" + safeVmName + "-" + r + ".log" + logBaseName := safeVmName + if destname != "" { + logBaseName = destname + } + LogFile := "/tmp/osm-nbdkit-" + logBaseName + "-" + r + ".log" logger.InitLogger(LogFile) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -536,6 +559,7 @@ func main() { HostPool: hostPool, }, ManageExtVol: externalVolume, + DestName: destname, OSMDataDir: osmdatadir, OSClient: provider, CBTSync: cbtsync, diff --git a/roles/convert_metadata/tasks/main.yml b/roles/convert_metadata/tasks/main.yml index c2b1dc16..2db2d05b 100644 --- a/roles/convert_metadata/tasks/main.yml +++ b/roles/convert_metadata/tasks/main.yml @@ -56,6 +56,7 @@ content: | { "vm_name": "{{ vm_import.vm_name }}", + "vm_dest_name": "{{ vm_import.vm_dest_name | default('') }}", "openstack": {{ vm_import.openstack | to_json }}, "vmware_guest_info": {{ guest_info | combine(vm_import.vmware_guest_info) | to_json }}, "migration": {{ vm_import.migration | to_json }} diff --git a/roles/convert_metadata/templates/import_workloads.json.j2 b/roles/convert_metadata/templates/import_workloads.json.j2 index f7a1390e..1f4b4388 100644 --- a/roles/convert_metadata/templates/import_workloads.json.j2 +++ b/roles/convert_metadata/templates/import_workloads.json.j2 @@ -1,5 +1,6 @@ { "vm_name": "{{ vm_name }}", + "vm_dest_name": "{{ vm_dest_name | default('') }}", "openstack": { "flavor_name_or_uuid": "{{ flavor_name_or_uuid }}", "openstack_private_network": "", diff --git a/roles/import_workloads/tasks/create_network_port.yml b/roles/import_workloads/tasks/create_network_port.yml index accc5342..c7346528 100644 --- a/roles/import_workloads/tasks/create_network_port.yml +++ b/roles/import_workloads/tasks/create_network_port.yml @@ -7,6 +7,7 @@ cloud: "{{ dst_cloud }}" os_migrate_nics_file_path: "{{ os_migrate_vmw_data_dir }}/{{ vm_name }}/nics.json" vm_name: "{{ vm_name }}" + destname: "{{ vm_dest_name | default('') }}" used_mapped_networks: true security_groups: ["{{ security_groups | default('default') }}"] use_fixed_ips: "{{ import_workloads_use_fixed_ips | default(false) | bool }}" @@ -27,6 +28,7 @@ cloud: "{{ dst_cloud }}" os_migrate_nics_file_path: "{{ os_migrate_vmw_data_dir }}/{{ vm_name }}/macs.json" vm_name: "{{ vm_name }}" + destname: "{{ vm_dest_name | default('') }}" used_mapped_networks: false security_groups: ["{{ security_groups | default('default') }}"] network_name: "{{ openstack_private_network }}" @@ -39,3 +41,4 @@ ansible.builtin.set_fact: nics: "{{ ports_uuid.ports | default([]) }}" when: os_migrate_create_network_port|default(true)|bool + diff --git a/roles/import_workloads/tasks/create_os_instance.yml b/roles/import_workloads/tasks/create_os_instance.yml index 1035a080..616ac5ba 100644 --- a/roles/import_workloads/tasks/create_os_instance.yml +++ b/roles/import_workloads/tasks/create_os_instance.yml @@ -15,14 +15,14 @@ - name: Get volume information for virt-v2v os_migrate.vmware_migration_kit.volume_info: cloud: "{{ dst_cloud }}" - name: "{{ vm_name }}-sda" + name: "{{ vm_dest_name | default(vm_name) }}-sda" register: volume_result when: import_workloads_os_migrate_virt_v2v - name: Get volume information for Cinder boot os_migrate.vmware_migration_kit.volume_info: cloud: "{{ dst_cloud }}" - name: "{{ vm_name }}" + name: "{{ vm_dest_name | default(vm_name) }}" register: cinder_volume_result when: import_workloads_boot_from_cinder @@ -71,6 +71,7 @@ cloud: "{{ dst_cloud }}" state: "present" name: "{{ vm_name }}" + destname: "{{ vm_dest_name | default('') }}" nics: "{{ nics }}" volumes: "{{ volumes_list }}" boot_volume: "{{ boot_volume_uuid }}" diff --git a/roles/import_workloads/tasks/nbdkit.yml b/roles/import_workloads/tasks/nbdkit.yml index 0853e03a..0df66acd 100644 --- a/roles/import_workloads/tasks/nbdkit.yml +++ b/roles/import_workloads/tasks/nbdkit.yml @@ -65,6 +65,7 @@ password: "{{ vcenter_password }}" server: "{{ vcenter_hostname }}" vmname: "{{ vm_name }}" + destname: "{{ vm_dest_name | default('') }}" volumeaz: "{{ import_workloads_cinder_az | default(omit) }}" volumetype: "{{ import_workloads_cinder_volume_type | default(omit) }}" assumezero: "{{ import_workloads_nbdkit_assume_zero | bool }}" From a62eca7ad67341a5741940cca06e651c11bd2bde Mon Sep 17 00:00:00 2001 From: root Date: Wed, 4 Mar 2026 06:50:58 +0100 Subject: [PATCH 2/2] fix: add missing moduleutils import in create_server --- plugins/modules/src/create_server/create_server.go | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/src/create_server/create_server.go b/plugins/modules/src/create_server/create_server.go index 9b166dd1..d7f569c8 100644 --- a/plugins/modules/src/create_server/create_server.go +++ b/plugins/modules/src/create_server/create_server.go @@ -20,6 +20,7 @@ import ( "context" "encoding/json" "os" + moduleutils "vmware-migration-kit/plugins/module_utils" "vmware-migration-kit/plugins/module_utils/ansible" "vmware-migration-kit/plugins/module_utils/logger" osm_os "vmware-migration-kit/plugins/module_utils/openstack"