Manual Pure vVOL VMware to Proxmox Migration Guide

Proxmox

Audience
Public
Source Type
Documentation

This guide walks through the complete manual process to migrate a VM from VMware vCenter to Proxmox VE using Everpure vVols. The migration will be to a LVM Thick volume.

Prerequisites

Access Requirements

  • VMware vCenter access with VM power management permissions

  • Everpure FlashArray access (GUI or CLI)

  • SSH root access to all Proxmox cluster nodes

  • The VM to migrate uses Everpure vVol storage

Proxmox Host Group

Ensure all Proxmox nodes are configured in a Everpure host group with proper FC/iSCSI initiators.

Proxmox Multipath Configuration

Ensure dm-multipath is installed and configured. Multipathd should be running and configured to auto-discover and add Everpure LUNs (blacklisting all devices except for Everpure LUNs and find_multipaths = off is recommended). This guide uses /dev/mapper devices for the cloned LUNs. This guide does not cover setting up multipath for general use. That should be done following the Proxmox and Everpure documentation.

Required Packages on Proxmox Nodes


               apt-get install -y sg3-utils multipath-tools 
            
  1. Identify Source VM and vVol Volumes

    1.1 Get VM Information from vCenter

    1. Log into vCenter

    2. Find the VM and note:

      • VM Name

      • Number of virtual disks

      • Datastore (should be vVol-based)

      • MAC addresses (for network preservation)

      • Firmware type (BIOS or EFI)

    1.2 Identify vVol Volume Names on Everpure

    Using Everpure GUI:

    1. Navigate to Storage > Volumes

    2. Filter or search for volumes containing the VM name

    3. The volumes with Data in the name are the vVol volumes for the VM

    4. Note the volume names (format: vvol-<vm-name>-<uuid>-<disk>)

    Using purecli:

    # List all volumes
    purevol list
    
    # Filter by VM name pattern
    purevol list | grep -i "<vm-name>"
    
    # Get volume details including serial
    purevol list --csv | grep -i "<vm-name>"
  2. Shutdown VMware VM

    2.1 Graceful Shutdown via vCenter

    1. Right-click the VM in vCenter

    2. Select Power > Shut Down Guest OS

    3. Wait for the VM to fully power off

    2.2 Alternative: Force Power Off (if guest tools not responding)

    1. Right-click the VM

    2. Select Power > Power Off

  3. Clone vVol Volumes on Everpure

    3.1 Using Everpure GUI

    For each vVol disk:
    1. Navigate to Storage > Volumes

    2. Find the source vVol volume

    3. Click the volume, then click Copy

    4. Enter a new name: proxmox-<vm-name>-disk-<N> (e.g., proxmox-myvm-disk-0)

    5. Click Copy

    6. Repeat this for any additional data volu

    3.2 Using purecli

    # Clone each vVol to a new volume
    purevol copy <source-vvol-name> <new-volume-name>
    
    # Example:
    purevol copy "vvol-myvm-abc123-virtualDisk-0" "proxmox-myvm-disk-0"
    
    # Get the serial of the new volume
    purevol list proxmox-myvm-disk-0 --csv
    
    # Repeat for each data volume

    3.3 Record Clone Information

    For each cloned volume, record:

    • Volume name: proxmox-myvm-disk-0

    • Serial number: (from purevol list)

    • WWN: 3624a9370 + serial_lowercase

    • Size in GB

  4. Prepare Proxmox Nodes (LVM Filter and kpartx Blocking)

    Before attaching the cloned LUNs to Proxmox, create filters to prevent LVM from activating volume groups and kpartx from creating partition mappings on the cloned disks.

    Note:

    Use the WWN from the cloned volumes (from Step 3), not the original source vVols.

    Note:

    Example WWN: Throughout this step, 3624a93708eabcb40cc4241b208501082 is used as an example. Replace this with your actual WWN from Step 3 (format: 3624a9370 + lowercase serial from the cloned volume).

    4.1 Add WWN to Filter List

    We will use /var/lib/migrator/filtered_wwns to track all WWNs currently being migrated. This serves several purposes:

    • Concurrent migrations: Multiple VMs can migrate at once, each with their own disks

    • Safe cleanup: When one migration finishes, only that disk's filter is removed while others remain protected

    • Persistence: The list survives reboots if a migration is interrupted

    On ALL Proxmox nodes, run:

    # Create directories
    mkdir -p /etc/lvm/lvm.conf.d
    mkdir -p /var/lib/migrator
    
    # Add WWN to the filter list (repeat for each disk)
    # This file tracks all active migration LUNs for safe cleanup later
    # Replace the example WWN with your actual WWN from Step 3
    echo "3624a93708eabcb40cc4241b208501082" >> /var/lib/migrator/filtered_wwns

    4.2 Create LVM Filter Configuration

    Create /etc/lvm/lvm.conf.d/pure-migrator.conf:

    # Replace the example WWN with your actual WWN from Step 3
    cat > /etc/lvm/lvm.conf.d/pure-migrator.conf << 'EOF'
    # Filters migration LUNs to prevent LVM activation
    devices {
        global_filter = [ "r|/dev/mapper/3624a93708eabcb40cc4241b208501082|", "a|.*|" ]
    }
    EOF

    For multiple disks, add each WWN as a reject rule:

    global_filter = [ "r|/dev/mapper/WWN1|", "r|/dev/mapper/WWN2|", "a|.*|" ]

    4.3 Create Udev Rule to Block kpartx

    Create /etc/udev/rules.d/59-migrator-skip-kpartx.rules:

    # Replace the example WWN with your actual WWN from Step 3
    cat > /etc/udev/rules.d/59-migrator-skip-kpartx.rules << 'EOF'
    # Skip kpartx for migration LUNs to prevent partition mapping
    KERNEL!="dm-*", GOTO="migrator_end"
    ACTION!="add|change", GOTO="migrator_end"
    ENV{DM_UUID}!="mpath-?*", GOTO="migrator_end"
    ENV{DM_NAME}=="3624a93708eabcb40cc4241b208501082", ENV{DM_SUBSYSTEM_UDEV_FLAG1}="1", GOTO="migrator_end"
    LABEL="migrator_end"
    EOF

    For multiple disks, add a line for each WWN before the LABEL line:

    ENV{DM_NAME}=="<wwn1>", ENV{DM_SUBSYSTEM_UDEV_FLAG1}="1", GOTO="migrator_end"
    ENV{DM_NAME}=="<wwn2>", ENV{DM_SUBSYSTEM_UDEV_FLAG1}="1", GOTO="migrator_end"

    4.4 Reload Udev Rules

    On ALL Proxmox nodes:

    udevadm control --reload-rules
  5. Attach Cloned Volumes to Proxmox Host Group

    5.1 Using Everpure GUI

    For each cloned volume:

    1. Navigate to Storage > Volumes

    2. Select the cloned volume

    3. Click Connected Hosts

    4. Click Connect

    5. Select Host Groups tab

    6. Select your Proxmox host group (e.g., proxmox-cluster)

    7. Click Connect

    5.2 Using purecli

    # Connect volume to host group
    purevol connect <volume-name> --hgroup <host-group-name>
    
    # Example:
    purevol connect proxmox-myvm-disk-0 --hgroup proxmox-cluster
    
    # Verify connection
    purevol listconnection proxmox-myvm-disk-0
  6. SCSI Rescan on All Proxmox Nodes

    On ALL Proxmox nodes, run:

    # Using rescan-scsi-bus.sh (recommended)
    rescan-scsi-bus.sh -a -r -u
    
    # If rescan-scsi-bus.sh not found, install sg3-utils first:
    apt-get install -y sg3-utils
    rescan-scsi-bus.sh -a -r -u
    
    # Alternative fallback if sg3-utils unavailable:
    for host in /sys/class/scsi_host/host*/scan; do echo '- - -' > $host 2>/dev/null; done
    for port in /sys/class/fc_host/host*/issue_lip; do echo 1 > $port 2>/dev/null; done

    6.1 Verify Multipath Devices Appeared

    # List multipath devices
    multipath -ll
    
    # Check for your WWN (use your actual WWN prefix)
    ls /dev/mapper/ | grep 3624a9370
    
    # Should see device WITHOUT partition suffixes (due to kpartx blocking):
    # Example: 3624a93708eabcb40cc4241b208501082
    # NOT:     3624a93708eabcb40cc4241b208501082-part1

    6.2 Verify No LVM VGs Activated

    # Should NOT show VGs from source VM
    vgs
    
    # Should NOT show source VM's LVs
    lvs
  7. Create Proxmox VM

    7.1 Get Next Available VMID

    pvesh get /cluster/nextid
    # Returns next available VMID, e.g., 108

    7.2 Create VM with Raw Disk

    # Create VM with basic settings
    # Replace these example values with your actual values
    VMID=108                                      # From Step 7.1
    VM_NAME="myvm"                                # Your VM name
    NODE="proxmox-02"                             # Target Proxmox node
    NETWORK="vmbr0"                               # Your network bridge
    WWN="3624a93708eabcb40cc4241b208501082"       # Your actual WWN from Step 3
    SCSIHW="pvscsi"                               # See Step 7.2.1 for mapping
    
    # Create VM
    # --ostype values: l26 = Linux 2.6+, win10 = Windows 10/Server 2016+, win11 = Windows 11/Server 2022
    qm create $VMID \
        --name "$VM_NAME" \
        --memory 8192 \
        --cores 4 \
        --sockets 1 \
        --cpu host \
        --scsihw $SCSIHW \
        --scsi0 "/dev/mapper/${WWN}" \
        --net0 "vmxnet3,bridge=${NETWORK}" \
        --ostype l26 \
        --boot order=scsi0

    ostype reference: l26 = Linux (kernel 2.6 or newer), win10 = Windows 10/Server 2016+, win11 = Windows 11/Server 2022+, other = generic. This optimizes QEMU settings for the guest OS. Match this to the source VM's OS.

    7.2.1 SCSI Controller Type Mapping

    The --scsihw parameter specifies the SCSI controller type. Match this to your source VMware VM's SCSI controller to ensure the guest OS has compatible drivers already installed.

    VMware to Proxmox SCSI Controller Mapping:

    VMware SCSI Controller Proxmox --scsihw Notes
    VMware Paravirtual (PVSCSI) pvscsi Most common for modern VMs. Best performance. Requires PVSCSI driver in guest.
    LSI Logic SAS megasas Common for Windows Server VMs. Uses MegaRAID SAS driver.
    LSI Logic Parallel lsi Legacy. Uses LSI 53C895A driver.
    BusLogic Parallel lsi Very old VMs. LSI is closest match.

    How to find your source VM's SCSI controller in VMware:

    # Using govc (VMware CLI)
    govc device.info -vm "VM_NAME" | grep -A5 "SCSI controller"
    
    # Or in vCenter UI:
    # VM -> Edit Settings -> Virtual Hardware -> SCSI Controller -> Type

    What happens if you use the wrong controller?

    • Wrong controller = guest won't boot (no driver for the disk controller)

    • The guest OS must have drivers for the SCSI controller type you choose

    • VMware VMs with PVSCSI have the pvscsi driver installed, so use pvscsi in Proxmox

    • If unsure and the source was a modern VMware VM, pvscsi is the safest choice

    Available Proxmox SCSI controller types:

    Proxmox scsihw Description Use Case
    pvscsi VMware Paravirtual SCSI VMware migrations (most common. Can be used for migrations but should be changed to virtio-scsi-single after migration)
    virtio-scsi-single VirtIO SCSI (single queue per disk) New Linux VMs with virtio drivers. Recommended for general use.
    virtio-scsi-pci VirtIO SCSI (multi-queue) Linux VMs
    megasas LSI MegaRAID SAS Windows servers, LSI SAS migrations
    lsi LSI 53C895A Legacy VMs, broad compatibility
    lsi53c810 LSI 53C810 Very old systems

    7.3 For EFI VMs (from VMware EFI guests)

    # Add EFI disk and BIOS type
    qm set $VMID --bios ovmf
    # Change "local-lvm" to your destination storage.
    qm set $VMID --efidisk0 local-lvm:1,efitype=4m,pre-enrolled-keys=0

    7.4 Preserve MAC Address (Optional but Recommended)

    # Set MAC address from source VM. Replace the example MAC with your actual MAC from the source VM.
    # Replace the example network adapter type with the actual type from the source VM or the desired type for the new VM. The example uses vmxnet3. Other common types are e1000 and virtio.
    qm set $VMID --net0 "vmxnet3,bridge=${NETWORK},macaddr=00:50:56:93:a0:00"

    7.5 Multiple Disks

    For VMs with multiple disks, add each disk:

    qm set $VMID --scsi1 "/dev/mapper/${WWN2}"
    qm set $VMID --scsi2 "/dev/mapper/${WWN3}"
  8. Start Proxmox VM
    qm start $VMID
    
    # Verify running
    qm status $VMID

    At this point, the VM is running from the raw multipath devices. The next step migrates the disks to Proxmox-managed storage.

  9. Live Migrate Disks to Proxmox Storage

    This step performs a live block copy from the raw /dev/mapper device to LVM-backed Proxmox storage using QEMU's QMP interface. The Proxmox GUI/API is not able to perform this operation due to the direct mapping of the storage in the VM config. An error will occur if attempted stating the system is unable to parse the volume ID as Proxmox expects the volume ID to be in the format of storage:vm-<vmid>-disk-<N>.

    9.1 Identify Target Storage VG

    # Check storage.cfg for your target storage
    # Replace "iscsi" with your actual storage ID
    cat /etc/pve/storage.cfg | grep -A5 "lvm: iscsi"
    
    # Note the vgname, e.g., "proxmox-cluster-pool"

    9.2 Get Source Disk Size

    blockdev --getsize64 /dev/mapper/${WWN}
    # Returns size in bytes, e.g., 107374182400 (100GB)
    
    # Convert to MB for LV creation
    SIZE_MB=$((107374182400 / 1024 / 1024))

    9.3 Create Target LV

    # This is the target VG for the destination VM disk
    VGNAME="proxmox-cluster-pool"
    LV_NAME="vm-${VMID}-disk-0"
    
    lvcreate -L ${SIZE_MB}M -n ${LV_NAME} ${VGNAME} -y -Wy
    
    # Verify LV exists
    lvs ${VGNAME}/${LV_NAME}

    9.4 Connect to QMP Socket

    The VM must be running. Connect to its QMP socket:

    # Verify socket exists
    ls -la /run/qemu-server/${VMID}.qmp

    9.5 Perform Live Mirror via QMP

    QMP requires a persistent session - all commands must be sent within the same connection. Use socat in interactive mode to maintain the session.

    9.5.1 Set Variables

    # Replace these example values with your actual values
    VMID=108                                      # Your VM ID from Step 7
    WWN="3624a93708eabcb40cc4241b208501082"       # Your actual WWN from Step 3
    VGNAME="proxmox-cluster-pool"        # Your target LVM volume group
    LV_NAME="vm-${VMID}-disk-0"
    LV_PATH="/dev/${VGNAME}/${LV_NAME}"
    QMP_SOCK="/run/qemu-server/${VMID}.qmp"

    9.5.2 Connect to QMP (Interactive Session)

    Start an interactive session that stays open:

    socat - UNIX-CONNECT:${QMP_SOCK}

    You'll see a greeting message like:

    {"QMP": {"version": {...}, "capabilities": ["oob"]}}
    Note:

    Keep this session open for all subsequent commands. Each command is typed/pasted and you'll see the response.

    9.5.3 Negotiate Capabilities

    Type this command (required before any other commands):

    {"execute": "qmp_capabilities"}

    Expected response: {"return": {}}

    9.5.4 Query Named Block Nodes

    Query the block device structure to identify the node names needed for the mirror operation.

    {"execute": "query-named-block-nodes"}

    Understanding the Output:

    QEMU creates a multi-layer block device stack. You'll see multiple entries for the same physical device with 3 layers:

    Layer 1 (Top):    drive-scsi0          [throttle driver]  <- Use for "device" parameter
                           |
    Layer 2 (Middle): ffa5d4038f11ff...    [raw driver]       <- Use for "replaces" parameter
                           |
    Layer 3 (Bottom): efa5d4038f11ff...    [host_device driver] -> /dev/mapper/3624a9370...

    Identify the three node names:

    1. Top throttle node - Look for:

      • "node-name": "drive-scsi0" (or drive-virtio0, drive-sata0, etc.)

      • "drv": "throttle"

      • "backing_file_depth": 1

      • Has a "children" array

    2. Child below throttle (raw driver) - Look in the throttle node's children array:

      • Find the entry with "child": "file"

      • Note the "node-name" (will be a hash like ffa5d4038f11ff4c1cbb20961716981)

      • This node will have "drv": "raw"

    3. Bottom host_device node - Look for:

      • "drv": "host_device"

      • "file": "/dev/mapper/3624a9370..." (your source device)

      • "children": [] (empty array)

      • Note the "node-name" (will be a hash like efa5d4038f11ff4c1cbb20961716981)

    Example from output:

    Top throttle node:

    {
      "node-name": "drive-scsi0",
      "drv": "throttle",
      "backing_file_depth": 1,
      "children": [
        {
          "node-name": "ffa5d4038f11ff4c1cbb20961716981",
          "child": "file"
        }
      ],
      ...
    }

    Child below throttle (raw driver):

    {
      "node-name": "ffa5d4038f11ff4c1cbb20961716981",
      "drv": "raw",
      "backing_file_depth": 0,
      "children": [
        {
          "node-name": "efa5d4038f11ff4c1cbb20961716981",
          "child": "file"
        }
      ],
      "file": "/dev/mapper/3624a93708eabcb40cc4241b208501082"
    }

    Bottom host_device node:

    {
      "node-name": "efa5d4038f11ff4c1cbb20961716981",
      "drv": "host_device",
      "backing_file_depth": 0,
      "children": [],
      "file": "/dev/mapper/3624a93708eabcb40cc4241b208501082"
    }

    Write down these three node names - you'll need them in the following steps.

    Common top-level device names:

    VM Disk Type  
    VirtIO-SCSI disk 0 drive-scsi0
    VirtIO-SCSI disk 1 drive-scsi1
    VirtIO-BLK disk 0 drive-virtio0
    SATA disk 0 drive-sata0
    IDE disk 0 drive-ide0

    9.5.5 Add Target Block Device

    Add the target LVM volume as a block device node.

    Replace the filename with your actual LVM path:

    {"execute": "blockdev-add", "arguments": {"driver": "raw", "node-name": "mirror-target-scsi0", "file": {"driver": "host_device", "filename": "/dev/proxmox-cluster-pool/vm-108-disk-0"}}}

    Parameters explained:

    • "driver": "raw" - No format, just raw block device

    • "node-name": "mirror-target-scsi0" - Temporary name for the target (must match disk number, e.g., mirror-target-scsi0, mirror-target-scsi1)

    • "filename" - Path to your LVM logical volume (from step 9.3)

    Expected response: {"return": {}}

    9.5.6 Start the Block Mirror

    Start the live block mirror operation using the node names from step 9.5.4.

    You need TWO node names from step 9.5.4: 1. Top throttle node (e.g., drive-scsi0) - for the device parameter 2. Child below throttle (e.g., ffa5d4038f11ff...) - for the replaces parameter

    {"execute": "blockdev-mirror", "arguments": {"job-id": "mirror-scsi0", "device": "drive-scsi0", "target": "mirror-target-scsi0", "sync": "full", "replaces": "ffa5d4038f11ff4c1cbb20961716981"}}

    Parameters explained:

    • "job-id": "mirror-scsi0" - Unique identifier for this mirror job (you choose this)

    • "device": "drive-scsi0" - Top throttle node from step 9.5.4

    • "target": "mirror-target-scsi0" - Node name you created in step 9.5.5

    • "sync": "full" - Copy all data (full synchronization)

    • "replaces": "ffa5d4038f11ff..." - Child below throttle (raw driver) from step 9.5.4

    Critical: The replaces parameter must be the child node below the throttle (the one with "drv": "raw"), NOT the bottom host_device node.

    Expected response: {"return": {}}

    9.5.7 Monitor Mirror Progress

    Run this command repeatedly to check progress:

    {"execute": "query-block-jobs"}

    Output shows progress:

    {"return": [{"device": "mirror-scsi0", "len": 107374182400, "offset": 53687091200, "ready": false, ...}]}
    • Calculate percentage: offset / len * 100

    • Wait until "ready": true appears

    9.5.8 Complete the Mirror (when ready=true)

    When the mirror job shows "ready": true, complete the switchover:

    {"execute": "block-job-complete", "arguments": {"device": "mirror-scsi0"}}

    Parameters explained:

    • "device": "mirror-scsi0" - The job-id from step 9.5.6

    Expected response: {"return": {}}

    Wait a few seconds for the job to finish.

    9.5.9 Verify Job Completed

    Verify the mirror job has completed:

    {"execute": "query-block-jobs"}

    Should return: {"return": []} (empty array means no jobs running).

    The VM is now using the target device (LVM volume).

    9.5.10 Verify Source Nodes Were Replaced (Optional)

    You can optionally verify that the replaces parameter worked correctly by querying the block nodes again:

    {"execute": "query-named-block-nodes"}

    Look for the drive-scsi0 node. You should see:

    • The children array now points to mirror-target-scsi0 instead of the old source node

    • The file field shows the target device path (e.g., /dev/nvme-tcp/vm-105-disk-0)

    • The old source nodes (e.g., ffa5d4038f11ff... and efa5d4038f11ff...) no longer exist

    Example of successful replacement:

    {
      "node-name": "drive-scsi0",
      "drv": "throttle",
      "children": [{"node-name": "mirror-target-scsi0", "child": "file"}],
      "file": "json:{...\"filename\": \"/dev/nvme-tcp/vm-105-disk-0\"...}"
    }

    What the replaces parameter did:

    • Automatically swapped the source node with the target node in the block device graph

    • Deleted the old source nodes (ffa5d4038f11ff... and efa5d4038f11ff...)

    • Released file descriptors on the old source device

    • The throttle node now points directly to the target device

    9.5.11 Exit QMP Session

    Exit the socat session:

    Press Ctrl+C

    9.5.12 Verify Device Released

    In a separate terminal (outside the QMP session):

    # Verify device is released - should show Open count: 0
    dmsetup info ${WWN} | grep "Open count"

    If the open count is 0, the source device has been successfully released and the VM is now running entirely on the target LVM volume.

    9.6 Update VM Configuration

    After the mirror completes, update the VM config to reference the LVM storage instead of the raw device:

    # Edit VM config
    nano /etc/pve/qemu-server/${VMID}.conf
    
    # Change the scsi0 line from (example WWN shown):
    #   scsi0: /dev/mapper/3624a93708eabcb40cc4241b208501082
    # To (use your storage name and LV name):
    #   scsi0: iscsi:vm-108-disk-0,size=100G

    Where iscsi is your Proxmox storage name and vm-108-disk-0 is the LV name you created in Step 9.3.

  10. Cleanup

    After the live mirror completes and the VM config is updated, clean up the temporary resources.

    10.1 Verify Device is No Longer in Use

    # Check open count - should be 0
    dmsetup info ${WWN} | grep "Open count"
    
    # If still in use, identify what's holding it:
    fuser -v /dev/mapper/${WWN}
    lsof /dev/mapper/${WWN}

    10.2 Remove Multipath Device from All Nodes

    On ALL Proxmox nodes:

    # Remove kpartx partition mappings (if any exist)
    kpartx -d /dev/mapper/${WWN}
    
    # Deactivate any LVM VGs on the device (if any were activated)
    # First identify VGs:
    pvs /dev/mapper/${WWN}*
    # Then deactivate:
    vgchange -an <vg-name>
    
    # Remove multipath device
    multipath -f ${WWN}
    
    # Verify device is gone
    ls /dev/mapper/ | grep ${WWN}  # Should return nothing

    10.3 Detach Volume from Host Group on Everpure

    Using Everpure GUI:
    1. Navigate to Storage > Volumes

    2. Select the cloned volume

    3. Click Connected Hosts

    4. Find the host group connection

    5. Click the X to disconnect

    Using purecli:

    purevol disconnect <volume-name> --hgroup <host-group-name>
    
    # Example:
    purevol disconnect proxmox-myvm-disk-0 --hgroup proxmox-cluster
    
    # Verify disconnected
    purevol listconnection proxmox-myvm-disk-0

    10.4 Delete Cloned Volume from Everpure

    Using Everpure GUI:
    1. Navigate to Storage > Volumes

    2. Select the cloned volume

    3. Click Destroy (moves to Destroyed Volumes)

    4. Optionally, go to Destroyed Volumes and Eradicate to permanently remove

    Using purecli:

    # Destroy volume (moves to destroyed state)
    purevol destroy <volume-name>
    
    # Eradicate (permanently delete)
    purevol eradicate <volume-name>
    
    # Example:
    purevol destroy proxmox-myvm-disk-0
    purevol eradicate proxmox-myvm-disk-0

    10.5 Remove LVM Filter and Udev Rules

    On ALL Proxmox nodes:

    # Remove WWN from filter list
    grep -v "^${WWN}$" /var/lib/migrator/filtered_wwns > /tmp/filtered_wwns.tmp
    mv /tmp/filtered_wwns.tmp /var/lib/migrator/filtered_wwns
    
    # If filter list is now empty, remove the config files:
    if [ ! -s /var/lib/migrator/filtered_wwns ]; then
        rm -f /etc/lvm/lvm.conf.d/pure-migrator.conf
        rm -f /etc/udev/rules.d/59-migrator-skip-kpartx.rules
        udevadm control --reload-rules
    fi
    
    # If other WWNs remain, rebuild the filter files manually
    # (See Step 2 for format)

Verification

Verify VM is Running on Proxmox Storage

# Check VM config shows storage syntax
cat /etc/pve/qemu-server/${VMID}.conf | grep scsi

# Output should be like:
# scsi0: iscsi:vm-108-disk-0,size=100G 
Verify LV Exists and is Active
lvs | grep vm-${VMID

Test Proxmox GUI Migration

After successful migration, you should be able to use the Proxmox GUI to:

  1. Move the VM between nodes
  2. Move disks between storage pools
  3. Take snapshots (if available)

Post-Migration Steps

Additional steps to take after migration to fully optimize the VM. These changes require installation of drivers, configuration changes, and a reboot of the VM.

  1. Remove VMware Tools

    VMware Tools can cause issues with Proxmox. It is recommended to remove VMware Tools and reboot the VM.

  2. Install virtio drivers and qemu-guest-agent

    The virtio drivers are much more efficient than the emulated devices. The qemu-guest-agent is required for Proxmox to be able to manage the VM (shutdown, reboot, etc.) and for the guest to be able to mount ISOs and have proper time sync.
    1. virtio drivers

      Download the virtio drivers from the Proxmox host to a local directory on the guest. The drivers are located in /usr/share/virtio-win/virtio-win.iso on the Proxmox host. Mount the ISO and install the drivers. A reboot may be required.

    2. qemu-guest-agent

      The qemu-guest-agent is available in the package manager of most Linux distributions and can be downloaded from the Proxmox host. The package is called qemu-guest-agent. Once installed, the service should be enabled and started. The VM will need to be rebooted for the agent to be available. While rebooting, configure Proxmox to enable the guest agent.

  3. Change the SCSI controller to virtio-scsi-single

    The pvscsi controller can be used, but virtio-scsi-single is recommended for Linux VMs. Windows VMs can use the megasas controller.

  4. Change the network adapter to virtio

    The vmxnet3 adapter can be used, but virtio is recommended for both Windows and Linux VMs.

  5. Enable HA for the VM

    HA should be enabled for the VM after the migration, as Proxmox does not do this by default. This can be done in the Proxmox GUI or CLI. The VM should be configured in Proxmox to enable HA.

Troubleshooting

Device has open count > 0 after mirror

Cause: kpartx created partition mappings or LVM activated VGs.

Solution:

# Check what's holding device open
dmsetup ls | grep ${WWN}

# If partition mappings exist:
kpartx -d /dev/mapper/${WWN}

# If LVM VGs are active:
vgs  # identify VG
vgchange -an <vg-name>

Mirror job not starting

Cause: QMP socket not found or drive name mismatch.

Solution:
# Verify VM is running on this node
qm status ${VMID}

# Check QMP socket exists
ls /run/qemu-server/${VMID}.qmp

# Query actual drive names via QMP
# The drive is typically "drive-scsi0" for scsi0 disk

multipath -f fails with "in use"

Cause: Something still has the device open.

Solution:

  1. Check for LVM: pvs /dev/mapper/${WWN}*
  2. Check for kpartx: ls /dev/mapper/ | grep ${WWN}
  3. Check processes: fuser -v /dev/mapper/${WWN}
  4. If udev-workers are stuck, you may need to reboot the node

Volume connection fails on Everpure

Cause: Host group doesn't exist or initiators not configured.

Solution:

  • Verify host group exists in Everpure
  • Verify all Proxmox node initiators (FC WWPN or iSCSI IQN) are in the host group

Quick Reference: WWN Construction

Example (replace with your actual serial from Everpure):

Pure Volume Serial: 8EABCB40CC4241B208501082           <- Get this from Pure Storage GUI or purecli
Pure NAA prefix:    3624a9370                          <- Always this prefix for Pure Storage
WWN:                3624a93708eabcb40cc4241b208501082  <- prefix + lowercase(serial)
Multipath device:   /dev/mapper/3624a93708eabcb40cc4241b208501082

Quick Reference: purecli Commands

# List volumes
purevol list

# Copy/clone volume
purevol copy <source> <dest>

# Connect to host group
purevol connect <volume> --hgroup <group>

# Disconnect from host group
purevol disconnect <volume> --hgroup <group>

# Destroy volume
purevol destroy <volume>

# Eradicate volume (permanent)
purevol eradicate <volume>

# List connections
purevol listconnection <volume>

Quick Reference: QMP Commands

// Negotiate capabilities (required first)
{"execute": "qmp_capabilities"}

// Query block nodes
{"execute": "query-named-block-nodes"}

// Add target block device
{"execute": "blockdev-add", "arguments": {"driver": "raw", "node-name": "target", "file": {"driver": "host_device", "filename": "/dev/vg/lv"}}}

// Start mirror
{"execute": "blockdev-mirror", "arguments": {"job-id": "mirror-scsi0", "device": "drive-scsi0", "target": "target", "sync": "full", "replaces": "source-node"}}

// Query job progress
{"execute": "query-block-jobs"}

// Complete mirror when ready
{"execute": "block-job-complete", "arguments": {"device": "mirror-scsi0"}}

// Delete orphaned source node
{"execute": "blockdev-del", "arguments": {"node-name": "source-node"}}