Программный анализ снимков qcow2: Полное руководство
Узнайте несколько методов извлечения информации о снимках qcow2 в форматах JSON, CSV и других машиночитаемых форматах для автоматизации. Полное руководство с примерами кода.
Как я могу программно извлечь информацию о снимках из файла qcow2 в машиночитаемом формате для целей автоматизации?
У меня есть файл qcow2, содержащий несколько снимков, и мне нужно программно перечислить теги снимков. Команда qemu-img snapshot -l предоставляет информацию о снимках, но выводит ее в человекочитаемом табличном формате:
$ qemu-img snapshot -l ./image.qcow2
Snapshot list:
ID TAG VM_SIZE DATE VM_CLOCK ICOUNT
1 appack-init 3.72 GiB 2025-10-29 17:43:38 0000:01:04.537 --
Какие существуют методы для извлечения этой информации о снимках в формате, подходящем для автоматизации, таком как JSON, CSV или другие структурированные форматы данных?
Программное извлечение информации о снимках из qcow2 файлов
Для программного извлечения информации о снимках из qcow2 файлов в машиночитаемом формате можно использовать несколько подходов, включая парсинг вывода qemu-img, использование QMP (QEMU Machine Protocol) или использование libvirt для автоматизации более высокого уровня. Команда qemu-img предоставляет возможности перечисления снимков, но для получения форматов, удобных для автоматизации, требуется парсинг вывода.
Содержание
- Использование qemu-img с парсингом вывода
- Подход с использованием QMP/QEMU Machine Protocol
- Интерфейс автоматизации Libvirt
- Техники и инструменты парсинга
- Полные примеры автоматизации
Использование qemu-img с парсингом вывода
Команда qemu-img snapshot -l является основой для извлечения информации о снимках, но её вывод по умолчанию имеет формат таблицы, удобный для чтения человеком. Для преобразования этого вывода в машиночитаемые форматы необходимо выполнить парсинг.
Базовая команда qemu-img
$ qemu-img snapshot -l ./image.qcow2 Snapshot list: ID TAG VM_SIZE DATE VM_CLOCK ICOUNT 1 appack-init 3.72 GiB 2025-10-29 17:43:38 0000:01:04.537 --
Стратегии парсинга
-
Текстовый парсинг с использованием регулярных выражений
bashqemu-img snapshot -l image.qcow2 | grep -v "Snapshot list:" | grep -v "^ID" | awk '{print $1","$2","$3","$4","$5","$6}' > snapshots.csv -
Структурированный вывод с использованием jq
bashqemu-img snapshot -l image.qcow2 | tail -n +3 | awk '{print "{\"id\": "$1", \"tag\": \""$2"\", \"size\": \""$3"\", \"date\": \""$4" "$5"\", \"vm_clock\": \""$6"\", \"icount\": \""$7"\"}"}' | jq -s '.' -
Python-скрипт для преобразования в JSON
pythonimport subprocess import json import re def get_snapshots_qcow2(image_path): result = subprocess.run(['qemu-img', 'snapshot', '-l', image_path], capture_output=True, text=True) lines = result.stdout.split('\n') snapshots = [] for line in lines: if line.startswith('ID') or line.startswith('Snapshot list'): continue if not line.strip(): continue parts = re.split(r'\s{2,}', line.strip()) if len(parts) >= 4: snapshot = { 'id': int(parts[0]), 'tag': parts[1], 'size': parts[2], 'date': f"{parts[3]} {parts[4]}" if len(parts) > 4 else parts[3], 'vm_clock': parts[5] if len(parts) > 5 else '', 'icount': parts[6] if len(parts) > 6 else '' } snapshots.append(snapshot) return snapshots # Использование snapshots = get_snapshots_qcow2('./image.qcow2') print(json.dumps(snapshots, indent=2))
Подход с использованием QMP/QEMU Machine Protocol
QMP предоставляет интерфейс на основе JSON для программного управления экземплярами QEMU, включая операции с снимками.
Пример команды QMP для работы со снимками
Как показано в документации QEMU, команды QMP используют формат JSON:
{
"execute": "blockdev-snapshot-sync",
"arguments": {
"device": "virtio0",
"snapshot-file": "/some/place/my-image",
"format": "qcow2"
}
}
Использование QMP для перечисления снимков
Для перечисления снимков через QMP обычно выполняются следующие шаги:
- Запустить QEMU с включенным QMP
- Подключиться к сокету QMP
- Отправить соответствующие команды запроса
- Распарсить JSON-ответы
import socket
import json
def query_snapshots_via_qmp(qmp_socket_path):
# Подключение к сокету QMP
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(qmp_socket_path)
# Отправка приветственного сообщения QMP
greeting = json.loads(sock.recv(1024).decode())
# Отправка согласования возможностей
sock.send(json.dumps({"execute": "qmp_capabilities"}).encode() + b"\n")
# Запрос информации о блочных устройствах
sock.send(json.dumps({"execute": "query-block"}).encode() + b"\n")
response = json.loads(sock.recv(1024).decode())
# Закрытие соединения
sock.close()
return response
Интерфейс автоматизации Libvirt
Libvirt предоставляет API более высокого уровня для управления платформами виртуализации и поддерживает операции с снимками.
Использование команды virsh
# Перечисление снимков для домена
virsh snapshot-list --domain vm-name --table
# Получение информации о снимке в формате XML
virsh snapshot-info --domain vm-name --snapshotname snapshot-name --xml
Пример с использованием Python и Libvirt
import libvirt
def get_snapshots_libvirt(conn_uri, domain_name):
conn = libvirt.open(conn_uri)
if conn is None:
raise Exception('Не удалось открыть соединение с гипервизором')
domain = conn.lookupByName(domain_name)
snapshots = domain.snapshotListNames()
snapshot_info = []
for snap_name in snapshots:
snapshot = domain.snapshotLookupByName(snap_name)
info = {
'name': snap_name,
'description': snapshot.getDescription(),
'creationTime': snapshot.getCreationTime(),
'state': snapshot.getState()
}
snapshot_info.append(info)
conn.close()
return snapshot_info
Техники и инструменты парсинга
Обработка текста со стандартными инструментами
Использование awk для преобразования в CSV:
qemu-img snapshot -l image.qcow2 | \
tail -n +3 | \
awk 'BEGIN {OFS=","} {print $1, $2, $3, $4" "$5, $6, $7}' > snapshots.csv
Использование sed для структурированного вывода:
qemu-img snapshot -l image.qcow2 | \
sed -n '3,$p' | \
sed 's/\s\{2,\}/,/g' | \
sed 's/^,//' > snapshots.csv
Продвинутый парсинг с использованием jq
qemu-img snapshot -l image.qcow2 | \
tail -n +3 | \
awk '{print "{\"id\": "$1", \"tag\": \""$2"\", \"size\": \""$3"\", \"date\": \""$4" "$5"\", \"vm_clock\": \""$6"\", \"icount\": \""$7"\"}"}' | \
jq -s '.' > snapshots.json
Пример для PowerShell в среде Windows
function Get-Qcow2Snapshots {
param([string]$ImagePath)
$output = qemu-img snapshot -l $ImagePath
$snapshots = @()
# Пропуск заголовочных строк
$dataLines = $output | Select-Object -Skip 2
foreach ($line in $dataLines) {
if ($line.Trim()) {
$parts = [regex]::Split($line.Trim(), '\s{2,}')
if ($parts.Count -ge 4) {
$snapshot = [PSCustomObject]@{
ID = [int]$parts[0]
Tag = $parts[1]
Size = $parts[2]
Date = "$($parts[3]) $($parts[4])"
VM_Clock = if ($parts.Count -gt 5) { $parts[5] } else { "" }
ICOUNT = if ($parts.Count -gt 6) { $parts[6] } else { "" }
}
$snapshots += $snapshot
}
}
}
return $snapshots | ConvertTo-Json -Depth 1
}
Полные примеры автоматизации
Bash-скрипт для вывода в формате CSV и JSON
#!/bin/bash
# qcow2_snapshot_extractor.sh
# Использование: ./qcow2_snapshot_extractor.sh <image.qcow2> [format]
IMAGE_PATH="$1"
FORMAT="${2:-json}"
if [[ ! -f "$IMAGE_PATH" ]]; then
echo "Ошибка: Файл образа не найден: $IMAGE_PATH"
exit 1
fi
# Получение данных о снимках
SNAPSHOT_DATA=$(qemu-img snapshot -l "$IMAGE_PATH")
# Пропуск заголовочных строк и обработка данных
PROCESSED_DATA=$(echo "$SNAPSHOT_DATA" | tail -n +3 | grep -v '^$')
if [[ "$FORMAT" == "csv" ]]; then
echo "ID,TAG,SIZE,DATE,VM_CLOCK,ICOUNT"
echo "$PROCESSED_DATA" | awk '{print $1","$2","$3","$4" "$5","$6","$7}'
elif [[ "$FORMAT" == "json" ]]; then
JSON_OUTPUT='['
FIRST=true
while read -r line; do
if [[ $FIRST == true ]]; then
FIRST=false
else
JSON_OUTPUT+=','
fi
parts=($(echo "$line" | tr -s ' '))
if [[ ${#parts[@]} -ge 4 ]]; then
date_part="${parts[2]} ${parts[3]}"
vm_clock_part="${parts[4]:-}"
icount_part="${parts[5]:-}"
JSON_OUTPUT+="{\"id\":${parts[0]},\"tag\":\"${parts[1]}\",\"size\":\"${parts[2]}\",\"date\":\"$date_part\",\"vm_clock\":\"$vm_clock_part\",\"icount\":\"$icount_part\"}"
fi
done <<< "$PROCESSED_DATA"
JSON_OUTPUT+=']'
echo "$JSON_OUTPUT" | jq .
else
echo "Неподдерживаемый формат: $FORMAT. Используйте 'csv' или 'json'"
exit 1
fi
Python-класс для управления снимками
import subprocess
import json
import re
from datetime import datetime
class Qcow2SnapshotManager:
def __init__(self, image_path):
self.image_path = image_path
self.snapshot_pattern = re.compile(r'\s{2,}')
def get_snapshots(self, output_format='json'):
"""Получение информации о снимках в указанном формате"""
try:
result = subprocess.run(
['qemu-img', 'snapshot', '-l', self.image_path],
capture_output=True,
text=True,
check=True
)
snapshots = self._parse_snapshot_output(result.stdout)
if output_format == 'json':
return json.dumps(snapshots, indent=2)
elif output_format == 'csv':
return self._format_csv(snapshots)
else:
raise ValueError(f"Неподдерживаемый формат вывода: {output_format}")
except subprocess.CalledProcessError as e:
raise Exception(f"Не удалось получить информацию о снимках: {e.stderr}")
def _parse_snapshot_output(self, output):
"""Парсинг вывода команды qemu-img snapshot"""
lines = output.split('\n')
snapshots = []
for line in lines:
if line.startswith('ID') or line.startswith('Snapshot list'):
continue
if not line.strip():
continue
parts = self.snapshot_pattern.split(line.strip())
if len(parts) >= 4:
snapshot = {
'id': int(parts[0]),
'tag': parts[1],
'size': parts[2],
'date': self._parse_date(parts[3], parts[4] if len(parts) > 4 else None),
'vm_clock': parts[5] if len(parts) > 5 else '',
'icount': parts[6] if len(parts) > 6 else ''
}
snapshots.append(snapshot)
return snapshots
def _parse_date(self, date_str, time_str=None):
"""Парсинг строк с датой и временем"""
if time_str:
return f"{date_str} {time_str}"
return date_str
def _format_csv(self, snapshots):
"""Форматирование снимков в CSV"""
csv_lines = ["ID,TAG,SIZE,DATE,VM_CLOCK,ICOUNT"]
for snap in snapshots:
csv_lines.append(f"{snap['id']},{snap['tag']},{snap['size']},"
f"\"{snap['date']}\",\"{snap['vm_clock']}\","
f"\"{snap['icount']}\"")
return '\n'.join(csv_lines)
def get_snapshot_tags(self):
"""Получение только списка тегов снимков"""
snapshots = self.get_snapshots_json()
return [snap['tag'] for snap in snapshots]
def get_snapshots_json(self):
"""Получение снимков в виде объектов Python"""
result = subprocess.run(
['qemu-img', 'snapshot', '-l', self.image_path],
capture_output=True,
text=True,
check=True
)
return self._parse_snapshot_output(result.stdout)
# Пример использования
if __name__ == "__main__":
manager = Qcow2SnapshotManager('./image.qcow2')
# Получение вывода в формате JSON
print("Вывод в формате JSON:")
print(manager.get_snapshots('json'))
# Получение вывода в формате CSV
print("\nВывод в формате CSV:")
print(manager.get_snapshots('csv'))
# Получение только тегов снимков
print("\nТеги снимков:")
print(manager.get_snapshot_tags())
Интеграция с CI/CD конвейерами
# Пример рабочего процесса GitHub Actions для анализа снимков
name: Анализ снимков Qcow2
on:
workflow_dispatch:
inputs:
image_path:
description: 'Путь к файлу образа qcow2'
required: true
default: './image.qcow2'
output_format:
description: 'Формат вывода (json/csv)'
required: true
default: 'json'
jobs:
snapshot-analysis:
runs-on: ubuntu-latest
steps:
- name: Checkout кода
uses: actions/checkout@v3
- name: Установка QEMU
run: sudo apt-get update && sudo apt-get install -y qemu-utils
- name: Извлечение информации о снимках
run: |
chmod +x scripts/qcow2_snapshot_extractor.sh
./scripts/qcow2_snapshot_extractor.sh ${{ inputs.image_path }} ${{ inputs.output_format }}
- name: Загрузка данных о снимках
uses: actions/upload-artifact@v3
with:
name: snapshot-data
path: snapshot_data.*
Источники
- Stack Overflow - Программное перечисление снимков qcow2 файла
- QEMU Wiki - Features/Snapshots
- Programster’s Blog - Qemu-img Cheatsheet
- Azer Technology - KVM-QEMU, QCOW2, QEMU-IMG и снимки
- Kashyap Chamarthy - Создание снимков с libvirt для qcow2 образов
- Server Fault - KVM снимки. Как увидеть содержимое qcow2 файла?
- Proxmox Support Forum - Расположение файла снимка qcow2
Заключение
Для программного извлечения информации о снимках из qcow2 файлов с целью автоматизации существуют несколько эффективных подходов:
- Парсить вывод qemu-img с помощью инструментов обработки текста, таких как awk, sed или пользовательских скриптов, для преобразования формата таблицы в JSON или CSV
- Использовать QMP/QEMU Machine Protocol для прямого JSON-взаимодействия с QEMU для более сложных сценариев автоматизации
- Воспользоваться libvirt для управления виртуализацией более высокого уровня с встроенной поддержкой снимков
- Создавать пользовательские скрипты автоматизации на Python, bash или других языках для обработки парсинга и форматирования в соответствии с требованиями
Наиболее практичный подход для большинства случаев использования - парсинг вывода qemu-img snapshot -l, так как он не требует запуска экземпляров QEMU и работает с существующими файлами qcow2. Приведенные примеры демонстрируют, как создавать надежные решения автоматизации, которые могут интегрироваться в CI/CD конвейеры, системы резервного копирования или инструменты управления виртуализацией.