MyTetra Share
Делитесь знаниями!
Скрипт для уменьшения размеров VDI-файлов в каталоге и подкаталогах
Время создания: 24.11.2022 15:07
Автор: xintrea
Текстовые метки: linux, VirtualBox, python, python3, скрипт, VDI, диск, размер, уменьшение, очистка
Раздел: Компьютер - Linux - Виртуализация и эмуляция - VirtualBox
Запись: xintrea/mytetra_syncro/master/base/1669291630i55g2cazwr/text.html на raw.github.com

Ниже приведен скрипт, который уменьшает размеры VDI-файлов дисков виртуальной машины VirtuslBox. Предполагается, что VDI-файлы имеют динамически изменяемый формат хранения.


Скрипт рекурсивно ищет все VDI-файлы в указанном каталоге и всех подкаталогах, и обрабатывает их. В среднем объем файлов образов дисков уменьшается на 30-60% для виртуальных машин, которые проработали некоторое время и в них устанавливались и удалялись какие-то пакеты, шла работа с переносом/копированием/удалением файлов, работала база данных.


Для работы скрипта в хостовой системе должна быть установлена утилита zerofree. Каталог /media/vdi должен быть заранее создан и доступен для записи. Скрипт вызывается с правами root, так как используются команды монтирования и создания символьных устройств.


Данный скрипт может пригодиться для массовой обработки виртуальных машин на сервере виртуализации. В момент выполнения скрипта виртуальные машины, диски которых обрабатываются, должны быть потушены, чтобы данные не были испорчены. Никаких проверок на то, что образ диска в данный момент занят в виртуальной машине, не предусмотрено.


Использование скрипта:



clearVdi.py <обрабатываемая_директория>



Код скрипта следующий:



#!/usr/bin/python3


# Данный скрипт принимает каталог, в котором он будет искать VDI-файлы.

# Поиск будет происходить также и в подкаталогах

# Каждый найденный файл образа будет обрабатываться через zerofree

# А так же данный файл будет уменьшаться через механизмы VirtualBox


import os

import sys

import re

import time

from subprocess import Popen, PIPE


def main():


if len(sys.argv)!=2 :

print("Не указан обрабатываемый каталог")

exit(1)


startDir=sys.argv[1]


if not os.path.isdir(startDir) :

print("Не найден каталог "+startDir)

exit(1)


if not os.path.isdir("/media/vdi") :

print("Не найден каталог для монтирования диска виртуальной машины /media/vdi")

exit(1)


vdiFiles = [os.path.join(dp, f) for dp, dn, filenames in os.walk(startDir) for f in filenames if os.path.splitext(f)[1] == '.vdi']


print("Будут обработаны файлы:")

print(vdiFiles)


keepBytes=0


for fileName in vdiFiles:

print("\nФайл "+fileName)


runSmart("Создание символьного устройства", "qemu-nbd -c /dev/nbd0 '"+fileName+"'")

runSmart("Монтирование диска "+fileName, "mount -o noatime,noexec,ro /dev/nbd0p1 /media/vdi")


sizeBefore=os.path.getsize(fileName)

print("Размер файла до обработки: "+'{0:,}'.format( sizeBefore ).replace(',', ' ') )


runSmart("Запуск zerofree", "zerofree -v /dev/nbd0p1")

runSmart("Размонтирование диска "+fileName, "umount /dev/nbd0p1")

runSmart("Отключение символьного устройства", "qemu-nbd -d /dev/nbd0")

runSmart("Уменьшение размера "+fileName, "vboxmanage modifymedium --compact '"+fileName+"'")


sizeAfter=os.path.getsize(fileName)

print("Размер файла после обработки: "+'{0:,}'.format( sizeAfter ).replace(',', ' ') )

print("Размер уменьшен на "+str(int(100-sizeAfter*100/sizeBefore))+"%")


keepBytes=keepBytes+(sizeBefore-sizeAfter)


print("Освобождено "+'{0:,}'.format( keepBytes ).replace(',', ' ')+" байт")



# Запуск команды с проверкой результата

def runSmart(title, command) :

print(title)

result=run(command)

time.sleep(1)

if result[2]!=0 :

print("Невозможно выполнить действие: "+title)

print(command)

print(result[0]+"\n"+result[1])

exit(1)



# Запуск внешней программы

def run(cmd) :

p=Popen(cmd, stdout=PIPE, shell=True)

stdOutData, stdErrData = p.communicate()

errCode=p.returncode


outData=""

errData=""


if not stdOutData is None :

outData=stdOutData.decode()


if not stdErrData is None :

errData=stdErrData.decode()


# Убирается последний перенос строк, чтобы в конце небыло пустой строки

outData=re.sub("\n$", '', outData )

errData=re.sub("\n$", '', errData )


return(outData, errData, errCode)


# Конструкция чтобы работала функция main()

if __name__ == '__main__':

main()



Пример работы скрипта:



Будут обработаны файлы:

['/opt/astra16up10_domain/Astra16up10DomainClient/Astra16up10DomainClient.vdi',

'/opt/astra16up10_domain/Astra16up10DomainClientMt2/Astra16up10DomainClientMt2.vdi',

'/opt/astra16up10_domain/Astra16up10DomainHost/Astra16up10DomainHost.vdi']


Файл /opt/astra16up10_domain/Astra16up10DomainClient/Astra16up10DomainClient.vdi

Создание символьного устройства

Монтирование диска /opt/astra16up10_domain/Astra16up10DomainClient/Astra16up10DomainClient.vdi

Размер файла до обработки: 10 874 781 696

Запуск zerofree

100.0%

Размонтирование диска /opt/astra16up10_domain/Astra16up10DomainClient/Astra16up10DomainClient.vdi

Отключение символьного устройства

Уменьшение размера /opt/astra16up10_domain/Astra16up10DomainClient/Astra16up10DomainClient.vdi

0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

Размер файла после обработки: 8 348 762 112

Размер уменьшен на 23%


Файл /opt/astra16up10_domain/Astra16up10DomainClientMt2/Astra16up10DomainClientMt2.vdi

Создание символьного устройства

Монтирование диска /opt/astra16up10_domain/Astra16up10DomainClientMt2/Astra16up10DomainClientMt2.vdi

Размер файла до обработки: 10 878 976 000

Запуск zerofree

100.0%

Размонтирование диска /opt/astra16up10_domain/Astra16up10DomainClientMt2/Astra16up10DomainClientMt2.vdi

Отключение символьного устройства

Уменьшение размера /opt/astra16up10_domain/Astra16up10DomainClientMt2/Astra16up10DomainClientMt2.vdi

0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

Размер файла после обработки: 8 370 782 208

Размер уменьшен на 23%


Файл /opt/astra16up10_domain/Astra16up10DomainHost/Astra16up10DomainHost.vdi

Создание символьного устройства

Монтирование диска /opt/astra16up10_domain/Astra16up10DomainHost/Astra16up10DomainHost.vdi

Размер файла до обработки: 14 773 387 264

Запуск zerofree

100.0%

Размонтирование диска /opt/astra16up10_domain/Astra16up10DomainHost/Astra16up10DomainHost.vdi

Отключение символьного устройства

Уменьшение размера /opt/astra16up10_domain/Astra16up10DomainHost/Astra16up10DomainHost.vdi

0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

Размер файла после обработки: 8 585 740 288

Размер уменьшен на 41%


Освобождено 11 221 860 352 байт


Так же в этом разделе:
 
MyTetra Share v.0.65
Яндекс индекс цитирования