-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3aea5ae
commit ce9d0e9
Showing
5 changed files
with
329 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# PVC helper scripts | ||
|
||
These helper scripts are included with the PVC client to aid administrators in some meta-functions. | ||
|
||
The following scripts are provided for use: | ||
|
||
## `migrate_vm` | ||
|
||
Migrates a VM, with downtime, from one PVC cluster to another. | ||
|
||
`migrate_vm <vm> <source_cluster> <destination_cluster>` | ||
|
||
### Arguments | ||
|
||
* `vm`: The virtual machine to migrate | ||
* `source_cluster`: The source PVC cluster; must be a valid cluster to the local PVC client | ||
* `destination_cluster`: The destination PVC cluster; must be a valid cluster to the local PVC client | ||
|
||
## `import_vm` | ||
|
||
Imports a VM from another platform into a PVC cluster. | ||
|
||
## `export_vm` | ||
|
||
Exports a (stopped) VM from a PVC cluster to another platform. | ||
|
||
`export_vm <vm> <source_cluster>` | ||
|
||
### Arguments | ||
|
||
* `vm`: The virtual machine to migrate | ||
* `source_cluster`: The source PVC cluster; must be a valid cluster to the local PVC client |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#!/usr/bin/env bash | ||
|
||
# export_vm - Exports a VM from a PVC cluster to local files | ||
# Part of the Parallel Virtual Cluster (PVC) system | ||
# | ||
# Copyright (C) 2018-2020 Joshua M. Boniface <[email protected]> | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
# | ||
############################################################################### | ||
|
||
set -o errexit | ||
set -o pipefail | ||
|
||
usage() { | ||
echo -e "Export a VM from a PVC cluster to local files." | ||
echo -e "Usage:" | ||
echo -e " $0 <vm> <source_cluster> [<destination_directory>]" | ||
echo -e "" | ||
echo -e "Important information:" | ||
echo -e " * The local user must have valid SSH access to the primary coordinator in the source_cluster." | ||
echo -e " * The user on the cluster primary coordinator must have 'sudo' access." | ||
echo -e " * If the VM is not in 'stop' state, it will be shut down." | ||
echo -e " * Do not switch the cluster primary coordinator while the script is running." | ||
echo -e " * Ensure you have enough space in <destination_directory> to store all VM disk images." | ||
} | ||
|
||
fail() { | ||
echo -e "$@" | ||
exit 1 | ||
} | ||
|
||
# Arguments | ||
if [[ -z ${1} || -z ${2} ]]; then | ||
usage | ||
exit 1 | ||
fi | ||
source_vm="${1}" | ||
source_cluster="${2}" | ||
if [[ -n "${3}" ]]; then | ||
destination_directory="${3}" | ||
else | ||
destination_directory="." | ||
fi | ||
|
||
# Verify the cluster is reachable | ||
pvc -c ${source_cluster} status &>/dev/null || fail "Specified source_cluster is not accessible" | ||
|
||
# Determine the connection IP | ||
cluster_address="$( pvc cluster list 2>/dev/null | grep -i "^${source_cluster}" | awk '{ print $2 }' )" | ||
|
||
# Attempt to connect to the cluster address | ||
ssh ${cluster_address} which pvc &>/dev/null || fail "Could not SSH to source_cluster primary coordinator host" | ||
|
||
# Verify that the VM exists | ||
pvc -c ${source_cluster} vm info ${source_vm} &>/dev/null || fail "Specified VM is not present on the cluster" | ||
|
||
echo "Verification complete." | ||
|
||
# Shut down the VM | ||
echo -n "Shutting down VM..." | ||
set +o errexit | ||
pvc -c ${source_cluster} vm shutdown ${source_vm} &>/dev/null | ||
shutdown_success=$? | ||
while ! pvc -c ${source_cluster} vm info ${source_vm} 2>/dev/null | grep '^State' | grep -q -E 'stop|disable'; do | ||
sleep 1 | ||
echo -n "." | ||
done | ||
set -o errexit | ||
echo " done." | ||
|
||
# Dump the XML file | ||
echo -n "Exporting VM configuration file... " | ||
pvc -c ${source_cluster} vm dump ${source_vm} 1> ${destination_directory}/${source_vm}.xml 2>/dev/null | ||
echo "done". | ||
|
||
# Determine the list of volumes in this VM | ||
volume_list="$( pvc -c ${source_cluster} vm info --long ${source_vm} 2>/dev/null | grep -w 'rbd' | awk '{ print $3 }' )" | ||
for volume in ${volume_list}; do | ||
volume_pool="$( awk -F '/' '{ print $1 }' <<<"${volume}" )" | ||
volume_name="$( awk -F '/' '{ print $2 }' <<<"${volume}" )" | ||
volume_size="$( pvc -c ${source_cluster} storage volume list -p ${volume_pool} ${volume_name} 2>/dev/null | grep "^${volume_name}" | awk '{ print $3 }' )" | ||
echo -n "Exporting disk ${volume_name} (${volume_size})... " | ||
ssh ${cluster_address} sudo rbd map ${volume_pool}/${volume_name} &>/dev/null || fail "Failed to map volume ${volume}" | ||
ssh ${cluster_address} sudo dd if="/dev/rbd/${volume_pool}/${volume_name}" bs=1M 2>/dev/null | dd bs=1M of="${destination_directory}/${volume_name}.img" 2>/dev/null | ||
ssh ${cluster_address} sudo rbd unmap ${volume_pool}/${volume_name} &>/dev/null || fail "Failed to unmap volume ${volume}" | ||
echo "done." | ||
done |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#!/usr/bin/env bash | ||
|
||
# import_vm - Imports a VM to a PVC cluster from local files | ||
# Part of the Parallel Virtual Cluster (PVC) system | ||
# | ||
# Copyright (C) 2018-2020 Joshua M. Boniface <[email protected]> | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
# | ||
############################################################################### | ||
|
||
set -o errexit | ||
set -o pipefail | ||
|
||
usage() { | ||
echo -e "Import a VM to a PVC cluster from local files." | ||
echo -e "Usage:" | ||
echo -e " $0 <destination_cluster> <destination_pool> <vm_configuration_file> <vm_disk_file_1> [<vm_disk_file_2>] [...]" | ||
echo -e "" | ||
echo -e "Important information:" | ||
echo -e " * At least one disk must be specified; all disks that are present in vm_configuration_file" | ||
echo -e " should be specified, though this is not strictly requireda." | ||
echo -e " * Do not switch the cluster primary coordinator while the script is running." | ||
echo -e " * Ensure you have enough space on the destination cluster to store all VM disks." | ||
} | ||
|
||
fail() { | ||
echo -e "$@" | ||
exit 1 | ||
} | ||
|
||
# Arguments | ||
if [[ -z ${1} || -z ${2} || -z ${3} || -z ${4} ]]; then | ||
usage | ||
exit 1 | ||
fi | ||
destination_cluster="${1}"; shift | ||
destination_pool="${1}"; shift | ||
vm_config_file="${1}"; shift | ||
vm_disk_files=( ${@} ) | ||
|
||
# Verify the cluster is reachable | ||
pvc -c ${destination_cluster} status &>/dev/null || fail "Specified destination_cluster is not accessible" | ||
|
||
# Determine the connection IP | ||
cluster_address="$( pvc cluster list 2>/dev/null | grep -i "^${destination_cluster}" | awk '{ print $2 }' )" | ||
|
||
echo "Verification complete." | ||
|
||
# Determine information about the VM from the config file | ||
parse_xml_field() { | ||
field="${1}" | ||
line="$( grep -F "<${field}>" ${vm_config_file} )" | ||
awk -F '>|<' '{ print $3 }' <<<"${line}" | ||
} | ||
vm_name="$( parse_xml_field name )" | ||
echo "Importing VM ${vm_name}..." | ||
pvc -c ${destination_cluster} vm define ${vm_config_file} 2>/dev/null | ||
|
||
# Create the disks on the cluster | ||
for disk_file in ${vm_disk_files[@]}; do | ||
disk_file_basename="$( basename ${disk_file} )" | ||
disk_file_ext="${disk_file_basename##*.}" | ||
disk_file_name="$( basename ${disk_file_basename} .${disk_file_ext} )" | ||
disk_file_size="$( stat --format="%s" ${disk_file} )" | ||
|
||
echo "Importing disk ${disk_file_name}... " | ||
pvc -c ${destination_cluster} storage volume add ${destination_pool} ${disk_file_name} ${disk_file_size}B 2>/dev/null | ||
pvc -c ${destination_cluster} storage volume upload ${destination_pool} ${disk_file_name} ${disk_file} 2>/dev/null | ||
done |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
#!/usr/bin/env bash | ||
|
||
# migrate_vm - Exports a VM from a PVC cluster to another PVC cluster | ||
# Part of the Parallel Virtual Cluster (PVC) system | ||
# | ||
# Copyright (C) 2018-2020 Joshua M. Boniface <[email protected]> | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
# | ||
############################################################################### | ||
|
||
set -o errexit | ||
set -o pipefail | ||
|
||
usage() { | ||
echo -e "Export a VM from a PVC cluster to another PVC cluster." | ||
echo -e "Usage:" | ||
echo -e " $0 <vm> <source_cluster> <destination_cluster> <destination_pool>" | ||
echo -e "" | ||
echo -e "Important information:" | ||
echo -e " * The local user must have valid SSH access to the primary coordinator in the source_cluster." | ||
echo -e " * The user on the cluster primary coordinator must have 'sudo' access." | ||
echo -e " * If the VM is not in 'stop' state, it will be shut down." | ||
echo -e " * Do not switch the cluster primary coordinator on either cluster while the script is running." | ||
echo -e " * Ensure you have enough space on the target cluster to store all VM disks." | ||
} | ||
|
||
fail() { | ||
echo -e "$@" | ||
exit 1 | ||
} | ||
|
||
# Arguments | ||
if [[ -z ${1} || -z ${2} || -z ${3} || -z ${4} ]]; then | ||
usage | ||
exit 1 | ||
fi | ||
source_vm="${1}" | ||
source_cluster="${2}" | ||
destination_cluster="${3}" | ||
destination_pool="${4}" | ||
|
||
# Verify each cluster is reachable | ||
pvc -c ${source_cluster} status &>/dev/null || fail "Specified source_cluster is not accessible" | ||
pvc -c ${destination_cluster} status &>/dev/null || fail "Specified destination_cluster is not accessible" | ||
|
||
# Determine the connection IPs | ||
source_cluster_address="$( pvc cluster list 2>/dev/null | grep -i "^${source_cluster}" | awk '{ print $2 }' )" | ||
destination_cluster_address="$( pvc cluster list 2>/dev/null | grep -i "^${destination_cluster}" | awk '{ print $2 }' )" | ||
|
||
# Attempt to connect to the cluster addresses | ||
ssh ${source_cluster_address} which pvc &>/dev/null || fail "Could not SSH to source_cluster primary coordinator host" | ||
ssh ${destination_cluster_address} which pvc &>/dev/null || fail "Could not SSH to destination_cluster primary coordinator host" | ||
|
||
# Verify that the VM exists | ||
pvc -c ${source_cluster} vm info ${source_vm} &>/dev/null || fail "Specified VM is not present on the source cluster" | ||
|
||
echo "Verification complete." | ||
|
||
# Shut down the VM | ||
echo -n "Shutting down VM..." | ||
set +o errexit | ||
pvc -c ${source_cluster} vm shutdown ${source_vm} &>/dev/null | ||
shutdown_success=$? | ||
while ! pvc -c ${source_cluster} vm info ${source_vm} 2>/dev/null | grep '^State' | grep -q -E 'stop|disable'; do | ||
sleep 1 | ||
echo -n "." | ||
done | ||
set -o errexit | ||
echo " done." | ||
|
||
tempfile="$( mktemp )" | ||
|
||
# Dump the XML file | ||
echo -n "Exporting VM configuration file from source cluster... " | ||
pvc -c ${source_cluster} vm dump ${source_vm} 1> ${tempfile} 2>/dev/null | ||
echo "done." | ||
|
||
# Import the XML file | ||
echo -n "Importing VM configuration file to destination cluster... " | ||
pvc -c ${destination_cluster} vm define ${tempfile} | ||
echo "done." | ||
|
||
rm -f ${tempfile} | ||
|
||
# Determine the list of volumes in this VM | ||
volume_list="$( pvc -c ${source_cluster} vm info --long ${source_vm} 2>/dev/null | grep -w 'rbd' | awk '{ print $3 }' )" | ||
|
||
# Parse and migrate each volume | ||
for volume in ${volume_list}; do | ||
volume_pool="$( awk -F '/' '{ print $1 }' <<<"${volume}" )" | ||
volume_name="$( awk -F '/' '{ print $2 }' <<<"${volume}" )" | ||
volume_size="$( pvc -c ${source_cluster} storage volume list -p ${volume_pool} ${volume_name} 2>/dev/null | grep "^${volume_name}" | awk '{ print $3 }' )" | ||
echo "Transferring disk ${volume_name} (${volume_size})... " | ||
pvc -c ${destination_cluster} storage volume add ${destination_pool} ${volume_name} ${volume_size} 2>/dev/null | ||
ssh ${source_cluster_address} sudo rbd map ${volume_pool}/${volume_name} &>/dev/null || fail "Failed to map volume ${volume} on source cluster" | ||
ssh ${destination_cluster_address} sudo rbd map ${volume_pool}/${volume_name} &>/dev/null || fail "Failed to map volume ${volume} on destination cluster" | ||
ssh ${source_cluster_address} sudo dd if="/dev/rbd/${volume_pool}/${volume_name}" bs=1M 2>/dev/null | pv | ssh ${destination_cluster_address} sudo dd bs=1M of="/dev/rbd/${destination_pool}/${volume_name}" 2>/dev/null | ||
ssh ${source_cluster_address} sudo rbd unmap ${volume_pool}/${volume_name} &>/dev/null || fail "Failed to unmap volume ${volume} on source cluster" | ||
ssh ${destination_cluster_address} sudo rbd unmap ${volume_pool}/${volume_name} &>/dev/null || fail "Failed to unmap volume ${volume} on destination cluster" | ||
done | ||
|
||
if [[ ${shutdown_success} -eq 0 ]]; then | ||
pvc -c ${destination_cluster} vm start ${source_vm} | ||
fi |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
client-cli/pvc.py usr/share/pvc | ||
client-cli/cli_lib usr/share/pvc | ||
client-cli/scripts usr/share/pvc |