Last active
March 14, 2024 22:24
-
-
Save tdewin/6a4738fd74b96b84d3fa7c5be78735fd to your computer and use it in GitHub Desktop.
Experimental migration tool from vSphere to Proxmox using Veeam Instant VM Recovery
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# MIT LICENSE | |
# EXPERIMENTAL RUN STEP BY STEP AND MAKE SURE YOU UNDERSTAND WHAT YOU ARE DOING | |
# EXPERIMENTAL RUN STEP BY STEP AND MAKE SURE YOU UNDERSTAND WHAT YOU ARE DOING | |
# EXPERIMENTAL RUN STEP BY STEP AND MAKE SURE YOU UNDERSTAND WHAT YOU ARE DOING | |
# EXPERIMENTAL RUN STEP BY STEP AND MAKE SURE YOU UNDERSTAND WHAT YOU ARE DOING | |
# EXPERIMENTAL RUN STEP BY STEP AND MAKE SURE YOU UNDERSTAND WHAT YOU ARE DOING | |
# By default vPowerNFS does not allow mounting by any host. You need to disable the vPowerNFS IP filter to do so | |
# https://www.veeam.com/kb1055 -> point 7 | |
# Key Location: HKLM\SOFTWARE\WOW6432Node\Veeam\Veeam NFS\ | |
# Value Name: vPowerNFSDisableIPAuth | |
# Value Type: DWORD (32-Bit) Value | |
# Value Data: 1 | |
# Start instant vm recovery, don't replace but do restore to another location | |
# name <name>_migrate to make sure the vm is unique and doesn't override | |
# where do you want the disks to live | |
# pvesh ls storage -o json | jq ".[] | .name" | |
TARGETSTORAGE="local-lvm" | |
#get started | |
#govc ls -json=true network | jq '[.elements[] | .Object] | map({ (.name):{"br":"",vlan:0}}) | add' | |
read -r -d '' NETMAPPING << EOM | |
{ | |
"VM Network": { | |
"br": "vmbr0", | |
"vlan": 0 | |
} | |
} | |
EOM | |
curl -L -o - "https://github.com/vmware/govmomi/releases/latest/download/govc_$(uname -s)_$(uname -m).tar.gz" | tar -C /usr/local/bin -xvzf - govc | |
apt update | |
apt install jq | |
read -s -p "pass (no echo): " esxipw | |
read -p "esxihost: " esxihost | |
export GOVC_INSECURE=1 | |
export GOVC_URL="https://root:$esxipw@$esxihost/sdk" | |
# This part should be only done once since vPowerNFS can be mounted once | |
NASSHARE=$(govc ls -json=true datastore | jq '.elements[] | .Object | select(.info.nas) | select(.info.nas.name | contains("VeeamBackup_"))') | |
NASHOST=$(echo $NASSHARE | jq ".info.nas.remoteHost" -r) | |
NASPATH=$(echo $NASSHARE | jq ".info.nas.remotePath" -r) | |
NASNAME=$(echo $NASSHARE | jq ".info.nas.name" -r) | |
VPOWERPATH="/mnt/$NASNAME" | |
mkdir -p "/mnt/$NASNAME" $VPOWERPATH | |
mount -t nfs "$NASHOST:$NASPATH" $VPOWERPATH | |
# Find the VM that you restore based on the _migrate tag | |
VMJSON=$(govc ls -json=true vm | jq '.elements[] | select(.Object.name | contains("_migrate")) | .Object') | |
VMNAME=$(echo $VMJSON | jq -r .name) | |
govc snapshot.revert -vm $VMNAME | |
govc snapshot.remove -vm $VMNAME "*" | |
#refresh | |
VMJSON=$(govc ls -json=true vm | jq '.elements[] | select(.Object.name | contains("_migrate")) | .Object') | |
DEVICESJSON=$(govc device.info -json=true -vm $VMNAME) | |
CPU=$(echo $VMJSON | jq ".config.hardware.numCPU" -r) | |
CORESSOCK=$(echo $VMJSON | jq ".config.hardware.numCoresPerSocket" -r) | |
MEM=$(echo $VMJSON | jq ".config.hardware.memoryMB" -r) | |
GUEST=$(echo $VMJSON | jq ".summary.config.guestId" -r) | |
#https://pve.proxmox.com/wiki/Manual:_qm.conf | |
#https://github.com/vmware/govmomi/blob/d62c0ace62357ba156e23b8f3e04667bf3ac6c36/simulator/guest_id.go#L59 | |
#https://github.com/vmware/ansible-vsphere-gos-validation/blob/c6d6b287e73c23472121b2cd22bb982ed5954550/linux/check_os_fullname/guest_id_mappings.json#L103 | |
#GUESTIDMAP=$(curl https://raw.githubusercontent.com/vmware/ansible-vsphere-gos-validation/c6d6b287e73c23472121b2cd22bb982ed5954550/linux/check_os_fullname/guest_id_mappings.json) | |
#echo $GUESTIDMAP | jq 'to_entries | map({(.value):{"ostype":"l26"}}) | add' | |
#GUESTMAPPING=$(curl https://gist.githubusercontent.com/tdewin/6a4738fd74b96b84d3fa7c5be78735fd/raw/aa7ebbf201bf8ebcfacb5da0b525714e0fb0db80/vmware-to-proxmox-map.json | jq ".guests") | |
read -r -d '' GUESTMAPPING << EOM | |
{ | |
"windows9_64Guest": { | |
"ostype": "win10" | |
}, | |
"windows11_64Guest": { | |
"ostype": "win11" | |
}, | |
"windows12_64Guest": { | |
"ostype": "win12" | |
}, | |
"windows9Server64Guest": { | |
"ostype": "win10" | |
}, | |
"windows2019srv_64Guest": { | |
"ostype":"win10" | |
}, | |
"windows2019srvNext_64Guest":{ | |
"ostype":"win11" | |
}, | |
"windows2022srvNext_64Guest":{ | |
"ostype":"win11" | |
}, | |
"centos7_64Guest": { | |
"ostype": "l26" | |
}, | |
"centos8_64Guest": { | |
"ostype": "l26" | |
}, | |
"centos9_64Guest": { | |
"ostype": "l26" | |
}, | |
"debian10Guest": { | |
"ostype": "l26" | |
}, | |
"debian10_64Guest": { | |
"ostype": "l26" | |
}, | |
"debian11Guest": { | |
"ostype": "l26" | |
}, | |
"debian11_64Guest": { | |
"ostype": "l26" | |
}, | |
"debian12Guest": { | |
"ostype": "l26" | |
}, | |
"debian12_64Guest": { | |
"ostype": "l26" | |
}, | |
"rhel6_64Guest": { | |
"ostype": "l26" | |
}, | |
"rhel7_64Guest": { | |
"ostype": "l26" | |
}, | |
"rhel8_64Guest": { | |
"ostype": "l26" | |
}, | |
"rhel9_64Guest": { | |
"ostype": "l26" | |
}, | |
"opensuseGuest": { | |
"ostype": "l26" | |
}, | |
"opensuse64Guest": { | |
"ostype": "l26" | |
}, | |
"slesGuest": { | |
"ostype": "l26" | |
}, | |
"sles12_64Guest": { | |
"ostype": "l26" | |
}, | |
"sles15_64Guest": { | |
"ostype": "l26" | |
}, | |
"sles16_64Guest": { | |
"ostype": "l26" | |
}, | |
"sles64Guest": { | |
"ostype": "l26" | |
}, | |
"suseGuest": { | |
"ostype": "l26" | |
}, | |
"suse64Guest": { | |
"ostype": "l26" | |
}, | |
"ubuntuGuest": { | |
"ostype": "l26" | |
}, | |
"ubuntu64Guest": { | |
"ostype": "l26" | |
}, | |
"rockylinux_64Guest": { | |
"ostype": "l26" | |
}, | |
"almalinux_64Guest": { | |
"ostype": "l26" | |
} | |
} | |
EOM | |
#https://github.com/vmware/govmomi/blob/32912767be55bf935264bf2b67c3f78514dcf23b/object/virtual_device_list.go#L66 | |
read -r -d '' NETDEVMAPPING << EOM | |
{ | |
"VirtualVmxnet3": { | |
"devtype":"vmxnet3" | |
}, | |
"VirtualE1000": { | |
"devtype":"e1000" | |
}, | |
"VirtualE1000e": { | |
"devtype":"e1000e" | |
} | |
} | |
EOM | |
OSTYPE=$(echo $GUESTMAPPING | jq ".[\"$GUEST\"].ostype" -r) | |
ORIGNAME=$(echo $VMJSON | jq ".name" -r | sed 's/_migrate$//g') | |
NEXTID=$(pvesh get /cluster/nextid) | |
BIOSTYPE=$(echo $VMJSON | jq ".config.firmware" -r) | |
BIOSTYPEMAPPING=$(echo '{"bios":"seabios","efi":"ovmf"}' | jq ".$BIOSTYPE" -r) | |
qm create $NEXTID --memory $MEM --cores $CORESSOCK --sockets $CPU --bios $BIOSTYPEMAPPING -ostype $OSTYPE --kvm yes --name $ORIGNAME | |
BIOSUUID=$(echo $VMJSON | jq ".config.uuid" -r) | |
qm set $NEXTID --smbios1 uuid=$BIOSUUID | |
NETWORKS=$(echo $DEVICESJSON | jq '[ .devices[] | select(.backing.network)]') | |
NLEN=$(echo $NETWORKS | jq length) | |
for i in $(seq 0 1 $(($NLEN-1))) | |
do | |
SAMPLENET=$(echo $NETWORKS | jq ".[$i]" -r) | |
MACADDR=$(echo $SAMPLENET | jq ".macAddress" -r) | |
VNET=$(echo $SAMPLENET | jq ".backing.deviceName" -r) | |
VNETMAPBR=$(echo $NETMAPPING | jq ".[\"$VNET\"].br" -r) | |
VNETMAPVLAN=$(echo $NETMAPPING | jq ".[\"$VNET\"].vlan" -r) | |
DEVTYPE=$(echo $SAMPLENET | jq ".type" -r) | |
DEVTYPEMAP=$(echo $NETDEVMAPPING | jq ".$DEVTYPE.devtype" -r) | |
echo $MACADDR $VNETMAPBR $VNETMAPVLAN $DEVTYPEMAP | |
qm set $NEXTID -net$i bridge=$VNETMAPBR,trunks=$VNETMAPVLAN,model=$DEVTYPEMAP,macaddr=$MACADDR | |
done | |
#DISKS=$(echo $VMJSON | jq '.config.hardware.device[] | select(.backing.fileName | index("vm"))') | |
DISKS=$(echo $VMJSON | jq '.layout.disk' ) | |
SORTEDDISKS=$(echo $DISKS | jq '. | sort_by(.key)') | |
DLEN=$(echo $SORTEDDISKS | jq length) | |
for i in $(seq 0 1 $(($DLEN-1))) | |
do | |
SAMPLEDISK=$(echo $VMJSON | jq ".layout.disk[$i] | .diskFile[0]" -r) | |
DISKPATH=$(echo $SAMPLEDISK | sed "s/\[$NASNAME\] //g") | |
echo $DISKPATH | |
[ -f "$VPOWERPATH/$DISKPATH" ] && qm disk import $NEXTID "$VPOWERPATH/$DISKPATH" $TARGETSTORAGE | |
done | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"guests": { | |
"windows9_64Guest": { | |
"ostype": "win10" | |
}, | |
"windows11_64Guest": { | |
"ostype": "win11" | |
}, | |
"windows12_64Guest": { | |
"ostype": "win12" | |
}, | |
"windows9Server64Guest": { | |
"ostype": "win10" | |
}, | |
"windows2019srv_64Guest": { | |
"ostype":"win10" | |
}, | |
"windows2019srvNext_64Guest":{ | |
"ostype":"win11" | |
}, | |
"windows2022srvNext_64Guest":{ | |
"ostype":"win11" | |
}, | |
"centos7_64Guest": { | |
"ostype": "l26" | |
}, | |
"centos8_64Guest": { | |
"ostype": "l26" | |
}, | |
"centos9_64Guest": { | |
"ostype": "l26" | |
}, | |
"debian10Guest": { | |
"ostype": "l26" | |
}, | |
"debian10_64Guest": { | |
"ostype": "l26" | |
}, | |
"debian11Guest": { | |
"ostype": "l26" | |
}, | |
"debian11_64Guest": { | |
"ostype": "l26" | |
}, | |
"debian12Guest": { | |
"ostype": "l26" | |
}, | |
"debian12_64Guest": { | |
"ostype": "l26" | |
}, | |
"rhel6_64Guest": { | |
"ostype": "l26" | |
}, | |
"rhel7_64Guest": { | |
"ostype": "l26" | |
}, | |
"rhel8_64Guest": { | |
"ostype": "l26" | |
}, | |
"rhel9_64Guest": { | |
"ostype": "l26" | |
}, | |
"opensuseGuest": { | |
"ostype": "l26" | |
}, | |
"opensuse64Guest": { | |
"ostype": "l26" | |
}, | |
"slesGuest": { | |
"ostype": "l26" | |
}, | |
"sles12_64Guest": { | |
"ostype": "l26" | |
}, | |
"sles15_64Guest": { | |
"ostype": "l26" | |
}, | |
"sles16_64Guest": { | |
"ostype": "l26" | |
}, | |
"sles64Guest": { | |
"ostype": "l26" | |
}, | |
"suseGuest": { | |
"ostype": "l26" | |
}, | |
"suse64Guest": { | |
"ostype": "l26" | |
}, | |
"ubuntuGuest": { | |
"ostype": "l26" | |
}, | |
"ubuntu64Guest": { | |
"ostype": "l26" | |
}, | |
"rockylinux_64Guest": { | |
"ostype": "l26" | |
}, | |
"almalinux_64Guest": { | |
"ostype": "l26" | |
} | |
}, | |
"netdevs": { | |
"VirtualVmxnet3": { | |
"devtype":"vmxnet3" | |
}, | |
"VirtualE1000": { | |
"devtype":"e1000" | |
}, | |
"VirtualE1000e": { | |
"devtype":"e1000e" | |
} | |
}, | |
"bios": {"bios":"seabios","efi":"ovmf"} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment