跳到主內容
版本:3.0

從快照還原虛擬機(執行個體)

本指南說明如何使用 snapshot-restore.sh 腳本,從已掛載的 OpenStack 磁碟的其中一個 Cinder 快照中還原該磁碟。

此腳本會提示您選擇專案、伺服器、已掛載的磁碟以及快照。 接著,它會關閉虛擬機,還原所選的 Ceph RBD 快照,然後重新啟動虛擬機。 如需完整的樣本還原工作流程,請參閱 完整還原作業的範例輸出

資料遺失風險

從快照還原磁碟會覆寫所有的磁碟資料。 您將失去快照建立後所做的任何變更。

開始之前

請確認執行此腳本的主機具備所需的 OpenStack 和 Ceph 存取權限。

透過 SSH 以 root 身分連線至叢集

瞭解如何使用 SSH 連線至 CubeCOS 叢集的 root shell,以執行管理任務。

  1. 開啟您的終端機。

  2. 請使用以下指令透過 SSH(安全殼層協定)連線至您的 CubeCOS 叢集:

    ssh root@<your-cluster-vip>
  3. 出現提示時,請輸入您的 SSH 密碼。

從快照還原磁碟

  1. 將腳本儲存為 snapshot-restore.sh。 請從 完整還原腳本 取得該腳本。

  2. 將腳本設為可執行。

    Make the restore script executable
    chmod +x snapshot-restore.sh
  3. 執行該腳本。

    Run snapshot-restore.sh
    ./snapshot-restore.sh
  4. 請輸入包含待還原虛擬機器的專案編號。

    Project selection
    Select a project by number:
    1. admin
    2. _diagnostics
    3. bigstack
    Enter the number: 3
  5. 請輸入您要還原的虛擬機編號。 您可以透過虛擬機名稱或 UUID 來識別虛擬機。

    Server selection
    Select a server by number:
    1. vm-snap-restore (52d7f3fa-4d6f-4868-b271-e018c78a061f)
    Enter the number: 1
  6. 請輸入要還原的磁碟編號。

    存放作業系統的根硬碟通常是 /dev/sda,而其餘的資料硬碟則位於較低的索引位置。 要識別每個磁碟,請前往 運算 > 虛擬機,選取要還原的虛擬機,然後按一下 磁碟 索引標籤以檢視磁碟的相關資訊。

    Volume selection
    Select a volume by number:
    1. d11dfee8-3067-4031-8e4d-da3bc867c913 (Device: /dev/sda)
    2. 684483a5-4bd6-448f-810a-81517d82754f (Device: /dev/sdb)
    Enter the number: 1
  7. 請輸入要還原的快照編號。

    Snapshot selection
    Select a snapshot by number:
    1. snapshot for add-data-v3 - Created: 2025-02-06 05:42:57
    2. snapshot for add-data-v1 - Created: 2025-02-06 05:42:11
    3. snapshot for snap-data - Created: 2025-02-06 02:01:19
    Enter the number: 1
  8. 確認還原。

    此腳本會顯示已選取的磁碟和快照 ID,並提示使用者確認:

    資料遺失

    從快照還原磁碟會覆寫所有的磁碟資料。 您將失去快照建立後所做的任何變更。

    Restore confirmation prompt
    WARNING: This operation will revert the volume
    (d11dfee8-3067-4031-8e4d-da3bc867c913) to the selected snapshot
    (50927e68-9330-46d6-bf8a-1dac0db8e652).
    The associated server will be SHUTDOWN, and all current disk data will be LOST.
    Type 'YES' to confirm:
    • 若要繼續,請輸入 YES
    • 若要取消,請輸入其他內容。

在還原完成後,請確認伺服器和磁碟區是否運作正常

腳本執行完畢後,請確認伺服器與已還原的磁碟區是否運作正常。

  1. 請確認伺服器狀態為 運作中
  2. 請確認預期的磁碟區是否仍已連接,且磁碟區狀態為 使用中
  3. 請登入虛擬機,並檢查已還原的資料或檔案系統的狀態。

完整還原腳本

snapshot-restore.sh
#!/bin/bash
source /etc/admin-openrc.sh

# Get the list of project names
projects=($(openstack project list -c Name -f value))

# Display the numbered list
echo "Select a project by number:"
for i in "${!projects[@]}"; do
echo "$((i+1)). ${projects[i]}"
done

# Read user input
read -p "Enter the number: " choice

# Validate input
if [[ $choice -ge 1 && $choice -le ${#projects[@]} ]]; then
project_name=(${projects[$((choice-1))]})
echo "You selected: ${projects[$((choice-1))]}"
else
echo "Invalid choice. Exiting."
exit 1
fi
## - End of Project -

# Get the list of servers (Name and ID)
mapfile -t servers < <(openstack server list --project="$project_name" --long -c Name -c ID -f value)

# Check if there are any servers
if [ ${#servers[@]} -eq 0 ]; then
echo "No servers found for project $project_name."
exit 1
fi

# Display the numbered list
echo "Select a server by number:"
for i in "${!servers[@]}"; do
selected_server_id=$(echo "${servers[i]}" | awk '{print $1}') # Extract server ID
server_name=$(echo "${servers[i]}" | awk '{$1=""; print $0}' | sed 's/^ *//') # Extract server name
echo "$((i+1)). $server_name ($selected_server_id)"
done

# Read user input
read -p "Enter the number: " choice

# Validate input
if [[ $choice -ge 1 && $choice -le ${#servers[@]} ]]; then
selected_server="${servers[$((choice-1))]}"
selected_server_id=$(echo "$selected_server" | awk '{print $1}') # Extract server ID
server_name=$(echo "$selected_server" | awk '{$1=""; print $0}' | sed 's/^ *//') # Extract server name
echo "You selected: $server_name ($selected_server_id)"
else
echo "Invalid choice. Exiting."
exit 1
fi
## - End of Server -

volumes_json=$(openstack server show "$selected_server_id" -c attached_volumes -f json)

# Extract volume IDs
mapfile -t volume_ids < <(echo "$volumes_json" | jq -r '.attached_volumes[].id')

# Check if there are any attached volumes
if [ ${#volume_ids[@]} -eq 0 ]; then
echo "No attached volumes found for server $selected_server_id."
exit 1
fi

# Get details of each attached volume
volume_info=()
for volume_id in "${volume_ids[@]}"; do
volume_json=$(openstack volume show "$volume_id" -c attachments -f json)
device=$(echo "$volume_json" | jq -r '.attachments[0].device')

# Store volume info (ID and device)
volume_info+=("$volume_id $device")
done

# Display numbered list
echo "Select a volume by number:"
for i in "${!volume_info[@]}"; do
volume_id=$(echo "${volume_info[i]}" | awk '{print $1}')
device=$(echo "${volume_info[i]}" | awk '{print $2}')
echo "$((i+1)). $volume_id (Device: $device)"
done

# Get user input
read -p "Enter the number: " choice

# Validate input
if [[ $choice -ge 1 && $choice -le ${#volume_info[@]} ]]; then
selected_volume_id=$(echo "${volume_info[$((choice-1))]}" | awk '{print $1}')
echo "You selected volume: $selected_volume_id"
else
echo "Invalid choice. Exiting."
exit 1
fi

## - End of Volume -

# Get all snapshots for the project "bigstack"
snapshots_json=$(openstack volume snapshot list --project="$project_name" --long -f json)

# Extract snapshots related to the selected volume
mapfile -t snapshot_info < <(echo "$snapshots_json" | jq -c --arg vol "$selected_volume_id" \
'.[] | select(.Volume == $vol) | {name: .Name, id: .ID, created_at: .["Created At"]}')

# Check if there are any snapshots
if [ ${#snapshot_info[@]} -eq 0 ]; then
echo "No snapshots found for volume: $selected_volume_id"
exit 1
fi

# Convert "Created At" to human-readable format and display options
echo "Select a snapshot by number:"
for i in "${!snapshot_info[@]}"; do
name=$(echo "${snapshot_info[i]}" | jq -r '.name') # Extract snapshot name
id=$(echo "${snapshot_info[i]}" | jq -r '.id') # Extract snapshot ID
created_at=$(echo "${snapshot_info[i]}" | jq -r '.created_at') # Extract Created At

# Convert to human-readable format
human_date=$(date -d "$created_at" '+%Y-%m-%d %H:%M:%S' 2>/dev/null)

# If date conversion fails, set a fallback
if [[ -z "$human_date" ]]; then
human_date="Invalid Date"
fi

echo "$((i+1)). $name - Created: $human_date"
done

# Get user selection
read -p "Enter the number: " choice

# Validate input
if [[ $choice -ge 1 && $choice -le ${#snapshot_info[@]} ]]; then
selected_snapshot_id=$(echo "${snapshot_info[$((choice-1))]}" | jq -r '.id') # Extract snapshot ID
echo "You selected snapshot: $selected_snapshot_id"
else
echo "Invalid choice. Exiting."
exit 1
fi

## - End of Snapshot -

# Ask for final confirmation
echo ""
echo "WARNING: This operation will revert the volume ($selected_volume_id) to the selected snapshot ($selected_snapshot_id)."
echo "The associated server will be SHUTDOWN, and all current disk data will be LOST."
echo ""
read -p "Type 'YES' to confirm: " confirmation

# Check if the user entered exactly "YES"
if [[ "$confirmation" != "YES" ]]; then
echo "Operation canceled. No changes were made."
exit 1
fi

# Proceed with the revert operation, ensure the server is SHUTOFF before proceeding
echo "Stopping the server ($selected_server_id)..."
openstack server stop "$selected_server_id"

# Wait until the server is fully stopped
echo "Waiting for server ($selected_server_id) to shut down..."
while true; do
vm_state=$(openstack server show "$selected_server_id" -c vm_state -f value)
if [[ "$vm_state" == "stopped" ]]; then
echo "✅ Server is now stopped."
break
fi
echo "⏳ Server is still stopping... checking again in 5 seconds."
sleep 5
done

echo "Reverting volume $selected_volume_id to snapshot $selected_snapshot_id..."
rbd snap rollback cinder-volumes/volume-"$selected_volume_id"@snapshot-"$selected_snapshot_id"

echo "Revert operation completed successfully."

echo "Starting the server ($selected_server_id)..."
openstack server start "$selected_server_id"

echo "Server started successfully."

完整還原作業的輸出範例

Example restore session
Select a project by number:
1. admin
2. _diagnostics
3. bigstack
Enter the number: 3
You selected: bigstack
Select a server by number:
1. vm-snap-restore (52d7f3fa-4d6f-4868-b271-e018c78a061f)
Enter the number: 1
You selected: vm-snap-restore (52d7f3fa-4d6f-4868-b271-e018c78a061f)
Select a volume by number:
1. d11dfee8-3067-4031-8e4d-da3bc867c913 (Device: /dev/sda)
2. 684483a5-4bd6-448f-810a-81517d82754f (Device: /dev/sdb)
Enter the number: 1
You selected volume: d11dfee8-3067-4031-8e4d-da3bc867c913
Select a snapshot by number:
1. snapshot for add-data-v3 - Created: 2025-02-06 05:42:57
2. snapshot for add-data-v1 - Created: 2025-02-06 05:42:11
3. snapshot for snap-data - Created: 2025-02-06 02:01:19
Enter the number: 1
You selected snapshot: 50927e68-9330-46d6-bf8a-1dac0db8e652

WARNING: This operation will revert the volume
(d11dfee8-3067-4031-8e4d-da3bc867c913) to the selected snapshot
(50927e68-9330-46d6-bf8a-1dac0db8e652).
The associated server will be SHUTDOWN, and all current disk data will be LOST.

Type 'YES' to confirm: YES
Stopping the server (52d7f3fa-4d6f-4868-b271-e018c78a061f)...
Waiting for server (52d7f3fa-4d6f-4868-b271-e018c78a061f) to shut down...
Server is still stopping. Checking again in 5 seconds.
Server is now stopped.
Reverting volume d11dfee8-3067-4031-8e4d-da3bc867c913 to snapshot 50927e68-9330-46d6-bf8a-1dac0db8e652...
Rolling back to snapshot: 100% complete...done.
Revert operation completed successfully.
Starting the server (52d7f3fa-4d6f-4868-b271-e018c78a061f)...
Server started successfully.

常見還原失敗的疑難排解

該腳本無法列出專案

請確認 /etc/admin-openrc.sh 檔案是否存在,且其中包含有效的 OpenStack 憑證。

要測試驗證功能:

Test OpenStack authentication
openstack project list

未列出任何伺服器

請確認所選專案中包含伺服器,且您的憑證具備讀取這些伺服器的權限:

List servers in a project
openstack server list --project PROJECT_NAME --long

未找到任何已掛載的磁碟區

請確認所選虛擬機已掛載磁碟:

Show attached server volumes
openstack server show SERVER_ID -c attached_volumes

未找到任何快照

請確認所選的磁碟在所選的專案中是否存在快照:

List volume snapshots
openstack volume snapshot list --project PROJECT_NAME --long

伺服器不會停止

檢查伺服器狀態與虛擬化平台狀態:

Check server state
openstack server show SERVER_ID -c status -c vm_state -c OS-EXT-SRV-ATTR:host

在伺服器停止運作之前,請勿執行 RBD 回滾。

還原失敗

請確認 Ceph 儲存池、磁碟標 ID 及快照 ID 是否正確:

List RBD snapshots for a volume
rbd snap ls cinder-volumes/volume-VOLUME_ID

接著請確認回滾目標是否存在:

Verify the rollback target
rbd info cinder-volumes/volume-VOLUME_ID@snapshot-SNAPSHOT_ID