
Введение
Когда требуется сделать резервную копию виртуальной машины какой-либо платформы виртуализации, обычно используется следующий подход: сначала добавляют в резервную копию информацию о конфигурации самой виртуальной машины, а затем уже содержание дисков этой виртуальной машины. При восстановлении резервной копии виртуальной машины эта же информация потребуется, чтобы создать экземпляр виртуальной машины на платформе виртуализации и в дальнейшем наполнить диски данными из резервной копии только что созданной виртуальной машины. Сегодня разберем, как это сделать на платформе VMware.
Дисклеймер
В "Группе Астра" есть собственные решения, входящие в портфель "Виртуализация\Частное облако". В настоящий момент мы работаем над созданием полноценного решения для резервного копирования как в частном, так и в публичном облаке. Однако процесс миграции бизнеса с зарубежных решений еще не завершен и будет продолжаться в будущем.
В своей рабочей практике команда RuBackup столкнулась с задачей создать резервную копию платформы VMvare. В данной статье мы будем описывать кейс, который был реализован на стороне клиента.
В случае работы с платформой виртуализации VMware мы в СРК RuBackup следуем этому же шаблону, но с учетом специфики данной платформы. Если информацию о конфигурации виртуальной машины мы получаем через REST API с хоста vCenter, то для работы с содержимым дисков виртуальной машины используется специальная проприетарная библиотека vixDiskLib производства VMware, написанная на языке программирования С. В данной статье подробно рассмотрим работу с этой библиотекой, а именно:
Получение информации о диске виртуальной машины
Бэкап диска виртуальной машины в резервную копию
Восстановление диска виртуальной машины из резервной копии в только что созданную виртуальную машину
В описанном кейсе берем версию 7 библиотеки vixDiskLib
, а также vCenter и esxi аналогичной версии. В качестве примера работы с библиотекой vixDiskLib
создателями библиотеки предлагается файл с кодом vixDiskLibSample.cpp
, содержащий пример использования библиотеки vixDiskLib
. Этот файл расположен в каталоге vmware-vix-disklib-distrib/doc/samples/diskLib
файла архива библиотеки. В данной статье мы модифицируем этот пример, чтобы он мог делать локальные резервные копии дисков виртуальной машины, а также восстанавливать эти резервные копии в заранее созданные диски ВМ на платформе виртуализации VMware.
Начало работы с программой-примером
Для запуска программы-примера библиотеки vixDiskLib из данной статьи вам потребуется ОС Linux, а также доступ к хосту vCenter для работы с платформой виртуализации VMware.
Давайте распакуем архив с библиотекой vixDiskLib
, соберем и запустим программу-пример. Для сборки этой программы сначала нужно убедится, что в вашу ОС Linux установлены пакеты компилятора gcc и утилиты make. Собрать нашу программу можно, перейдя в каталог vmware-vix-disklib-distrib/doc/samples/diskLib
и выполнив команду make
.
Для работы рассматриваемой программы-примера нужно указать следующие параметры командной строки:
host: адрес хоста, где находится vCenter. Предположим, что данный хост находится по адресу vcenter.corp.ru. Убедитесь, что этот адрес корректно обрабатывается службой работы с доменными именами DNS. Обычно для этого нужно добавить соответствующую запись в файл
/etc/hosts
, или в конфигурацию вашего DNS сервера.user: имя пользователя vCenter. Предположим, что это rubackup
password: пароль для пользователя vCenter rubackup, предположим, что это P@ssword!
thump: контрольная сумма https сертификата хоста vCenter. По сути, это набор двузначных шестнадцатеричных чисел, разделенных двоеточием. Для хоста vCenter эту контрольную сумму можно получить при помощи утилиты openssl консольной командой:
openssl s_client -connect vcenter.corp.ru:443 < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin
. Также эту информацию можно получить с помощью вашего веб-браузера, если зайти по адресу vcenter.corp.ru. В случае Mozilla Firefox нужно правой кнопкой мыши кликнуть по иконке безопасности в адресной строке, далее выбрать пункт "Защищенное соединение", затем "Подробнее". В открывшимся окне "Информация о странице" нужно нажать кнопку "Просмотреть сертификат", далее найти поле "Отпечатки" и напротив строки "SHA-1" и будет искомое значение.Для получения этой же информации другими веб-браузерами обратитесь к документации соответствующего веб-броузера.
vm: уникальный идентификатор виртуальной машины для vCenter.
vixDiskLib
не позволяет просто так обратится к виртуальному жесткому диску, нужно обязательно указать идентификатор виртуальной машины, к которой подсоединен интересующий нас виртуальный жесткий диск. Есть несколько способов узнать этот идентификатор, в частности, с помощью веб-браузера это можно сделать, зайдя на сайт vCenter. Кликните мышкой по интересующей вас виртуальной машине и обратите внимание на адресную строку. Она будет выглядеть примерно так: "https://vcenter.corp.ru/ui/app/vm;nav=v/urn:vmomi:VirtualMachine:vm-1111:1ba1ac11-3d4a-425b-8b9f-9f76b501191a/summary". То, что выделено vm-1111, и будет уникальным идентификатором виртуальной машины. Такой идентификатор называется MoRef (Management Object Reference). Он начинается со строки vm, далее через тире будет указан уникальный идентификатор виртуальной машины для данного vCenter. Для программы-примера полностью значение этого параметра будет выглядеть так: "moref=vm-1111".Следующим параметром будет имя команды, которую требуется осуществить при данном вызове программы-примера. Мы рассмотрим команды позднее.
Последний параметр - это непосредственно полный путь до виртуального жесткого диска ВМ на удаленном датасторе, для которого мы хотим осуществить операцию, заданную в пункте 6. Полный путь состоит из имени датастора и расположения файла виртуального жесткого диска на этом датасторе. Самый простой способ получить такой путь - это использовать веб-браузер, зайдя на хост vCenter. У интересующей вас виртуальной машины нажмите ссылку "Редактирование", раскройте выпадающий список с интересующим вас виртуальным жестким диском и скопируйте значение поля "Disk File".
В данном случае полный пусть диска выглядит так: "[datastore] test_vm/test_vm.vmdk", где "[datastore]" это имя датастора, "test_vm" - имя папки в датасторе, где содержится виртуальная машина, "test_vm.vmdk" имя диска. Так как этот параметр содержит пробел, то при работе из оболочки командной строки его обязательно надо заключать в одинарные или двойные кавычки, или же экранировать согласно правилам используемой оболочки командной строки.
Давайте же запустим программу-пример, но перед этим для простоты зададим переменную окружения, в которой определим все неизменяемые параметры:
export VCENTER_PARAMS="-host vcenter.corp.ru -user rubackup -password 'P@ssworD1' -thumb 11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44"
В дальнейшем будем использовать эту переменную при запуске нашей программы-примера. Если вы используете в имени пользователя или пароля какие-либо специальные символы, не забывайте их экранировать согласно правилам вашей оболочки командной строки. Для запуска программы-примера перейдем в каталог командой cd ~/vmware-vix-disklib-distrib/doc/samples/diskLib
Так как программа-пример использует разделяемые библиотеки vixDiskLib
, зададим пути их поиска через переменную среды окружения LD_LIBRRAY_PATH
:
export LD_LIBRARY_PATH=~/vmware-vix-disklib-distrib/lib64/
Нужно учитывать, что все запуски программы-примера мы будем делать для выключенной виртуальной машины, так как vCenter не разрешает одновременное открытие одного и того же виртуального жесткого диска разными сущностями. В нашем тестовом примере мы делаем резервную копию диска у выключенной виртуальной машины, но при реальной работе СРК перед началом процедуры бэкапа у работающей виртуальной машины создается снэпшот и СРК добавляет в резервную копию данные уже из снэпшота, не прерывая работу виртуальной машины.
Далее запустим программу-пример с командой info, которая запрашивает у виртуального жесткого диска базовую информацию.
$ ./vix-disklib-sample $VCENTER_PARAMS -vm moref=1111 -info '[datastore] test_vm/test_vm.vmdk'
Disk[0] "[datastore] test_vm/test_vm.vmdk" is opened using transport mode "nbd".
capacity = 419430400 sectors
logical sector size = 512 bytes
physical sector size = 512 bytes
number of links = 1
adapter type = LsiLogic SCSI
BIOS geometry = 0/0/0
physical geometry = 26108/255/63
Transport modes supported by vixDiskLib: file:nbdssl:nbd
Disk[0] is closed.
Если эта команда выполнилась успешно и вывела результат, то значит ваша программа-пример построена и сконфигурирована корректно. Далее будем приводить только ту часть вывода из примера, которая представляет для нас непосредственный интерес. Остальное опустим, поскольку объем очень большой.
Самая важная для нас строчка в этом выводе - capacity = 419430400 sectors
, которая говорит, что размер диска составляет 419430400 секторов виртуального жесткого диска. Каждый такой сектор имеет размер в 512 байт.
Бэкап виртуального жесткого диска
Наша задача - сделать резервную копию виртуального жесткого диска виртуальной машины. Поэтому для нас важна команда dump
программы-примера, которая позволяет вывести содержимое секторов виртуального жесткого диска, заданных параметрами start
и count
.
Выведем для примера 10 и 11 секторы диска, используя команду dump:
$ ./vix-disklib-sample $VCENTER_PARAMS -vm moref=1111 -dump -start 10 -count 2 '[datastore] test_vm/test_vm.vmdk'
0000 : b2 c3 68 b9 d4 76 e5 1b e2 99 d3 b4 a2 d7 eb 0e ..h..v..........
0010 : f7 f4 77 d8 96 3d 15 e0 c8 69 32 d1 34 24 f7 50 ..w..=...i2.4$.P
0020 : 60 d8 9b 07 3d e3 c2 43 3e 21 e5 0b 6c e2 04 cc `...=..C>!..l...
0030 : ad c5 8c b8 49 18 7a 25 4f fd 49 29 8c 52 4a 3a ....I.z%O.I).RJ:
0040 : c6 7f dc d8 f9 f6 7e fd 14 34 2e 55 1b 2d 16 f2 ......~..4.U.-..
0050 : 86 5c f6 35 1f 30 bd 82 8d 8e 49 bd ed 84 44 72 .\.5.0....I...Dr
0060 : 7c 93 af 47 4a 5d e3 02 3a 0d 68 bb d9 6a 7d a2 |..GJ]..:.h..j}.
Если у нас есть возможность выводить содержимое диска из произвольного места, то таким образом мы можем сделать функцию, которая скопирует содержимое удаленного виртуального жесткого диска в локальный файл. Давайте добавим в программу-пример новую команду localdump
, которая сделает копию диска с удаленного датастора в локальный файл.
#define LOCAL_DUMP_FILE "vm_disk_local_dump"
static void
DoLocalDump(void) {
VixDisk disk(appGlobals.connection, appGlobals.diskPaths[0].c_str(), appGlobals.openFlags);
const VixDiskLibInfo* info = disk.getInfo();
std::ofstream output_file(LOCAL_DUMP_FILE, std::ios::out | std::ios::binary);
if(output_file) {
const unsigned num_sectors = 1000;
std::vector<uint8> buf(VIXDISKLIB_SECTOR_SIZE * num_sectors);
VixDiskLibSectorType i;
for (i = 0; i < info->capacity; i += num_sectors) {
unsigned read_sectors = num_sectors;
if(i + num_sectors > info->capacity) {
read_sectors = info->capacity - i;
}
VixError vixError = VixDiskLib_Read(disk.Handle(),
i,
read_sectors, buf.data());
CHECK_AND_THROW(vixError);
output_file.write((char*)&buf[0], read_sectors * VIXDISKLIB_SECTOR_SIZE);
}
} else {
std::cerr<<"Error open file:"<<LOCAL_DUMP_FILE<<std::endl;
}
}
В данном коде при передаче нашей программе-примеру команды localdump
будет вызван обработчик этой команды - функция DoLocalDump
. Внутри этой функции мы создаем объект виртуального жесткого диска для получения размера виртуального жесткого диска и его хэндла. Далее в цикле содержимое виртуального жесткого диска копируется во временный буфер с помощью вызова функции VixDiskLib_Read
, а затем последовательно сохраняется в локальный файл.
Как проверить, соответствует ли наша резервная копия виртуального диска оригинальному виртуальному жесткому диску?
Самый простой способ, - вычислить md5 сумму у диска-копии и оригинального диска, ведь в данном случае мы копируем диск целиком, как есть. Для локальной копии диска, полученной программой-примером, это можно сделать, запустив команду ms5sumvm_disk_local_dump
. Для оригинального диска нужно зайти по ssh на хост-гипервизор VMware по ssh, далее перейти в в папку, соответствующую датастору интересующего диска, и также выполнить команду: md5sum /vmfs/volumes/14171d1d-d161610a-1f18-141715181f14/test_vm/test_vm-flat.vmdk
. В этой команде /vmfs/volumes/14171d1d-d161610a-1f18-141715181f14
является путем до корневой папки датастора, test_vm
- папкой виртуальной машины, test_vm-flat.vmdk
- файлом виртуального жесткого диска с данными. Реальные значения будут зависеть от вашей конфигурации среды виртуализации VMware.
Важно учитывать, что этот способ будет работать только в том случае если, виртуальная машина, содержащая этот виртуальный жесткий диск, не содержит снэпшотов.
Такая процедура бэкапа будет актуальна для так называемых толстых виртуальных жестких дисков, то есть тех, которые аллоцируют все свое дисковое пространство на момент своего создания, или же дисков, заполненных на 100% своего номинального размера. Но VMware также позволяет создавать диски, которые аллоцируют дисковое пространство по мере надобности, то есть в процессе работы виртуальной машины. Такой подход несколько более медленный для работы виртуальной машины, чем предыдущий, но позволяет более экономно расходовать свободное дисковое пространство на датасторе. Чтобы узнать, все ли дисковое пространство виртуального жесткого диска аллоцировано на момент его бэкапа или нет, можно воспользоваться командой getallocatedblocks
у программы-примера. Для диска, который уже аллоцировал все свое дисковое пространство, вывод команды будет выглядеть так:
$ ./vix-disklib-sample $VCENTER_PARAMS -vm moref=1111 -getallocatedblocks -chunksize 128 '[datastore] test_vm/test_vm.vmdk'
Disk[0] "[datastore] test_vm/test_vm.vmdk" is opened using transport mode "nbd".
Number of blocks: 1
Offset Length
0x000000000000 0x000000400000
allocated size (4194304) / capacity (4194304) : 100%
Disk[0] is closed.
Обратите внимание на значение allocated size 100%
. Такой диск вполне можно забэкапить способом, описанным выше. Но если вывод команды выглядит так, как ниже, использовать описанный ранее метод бэкапа диска будет неэффективно:
$ ./vix-disklib-sample $VCENTER_PARAMS -vm moref=1111 -getallocatedblocks -chunksize 128 '[datastore] test_vm/test_vm.vmdk'
Disk[0] "[datastore] test_vm/test_vm.vmdk" is opened using transport mode "nbd".
Number of blocks: 303
Offset Length
0x000000000000 0x000000001800
0x000000100800 0x00000001E800
<omited>
0x000018D41000 0x000000006800
0x000018D48000 0x000000006000
0x000018FFF000 0x000000001000
allocated size (102545408) / capacity (419430400) : 24%
Disk[0] is closed.
Обратите внимание на значение процента в строчке, начинающейся с allocated size. Значение в 24% сообщает, что не все пространство виртуального жесткого диска аллоцировано. В свою очередь это означает, что мы можем поместить в резервную копию только аллоцированные части, а это может уменьшить время бэкапа и сократит размер резервной копии по сравнению с бэкапом, сделанным первым способом. Метод бэкапа в таком случае можно примерно описать как:
Получаем карту аллоцированных блоков виртуального жесткого диска виртуальной машины, сохраняем ее в резервную копию.
Сохраняем каждый блок из карты аллоцированных блоков опять же в резервную копию.
Но у такого способа бэкапа виртуального жесткого диска все же есть и минусы: процедура получения списка аллоцированных блоков может быть долгой. Особенно это актуально для виртуальных жестких дисков, виртуальная машина которых имеет много снэпшотов. Также это может занять много времени в случаях, у которых периодически создавались и удалялись снэпшоты, но не выполнялась операция консолидации виртуальных жестких дисков. Для поддержания оптимальной производительности виртуальных машин следует хранить только те снэпшоты виртуальных машин, которые действительно нужны, и регулярно выполнять операцию консолидации виртуальных жестких дисков виртуальных машин.
Для этого в веб-интерфейсе vCenter вызовите контекстное меню для интересующей вас виртуальной машины, далее выберите пункты "Snapshots"→"Consolidate". Эти же пункты меню актуальны и для веб-интерфейса гипервизора esxi. Для виртуальных жестких дисков, у которых суммарный объем аллоцированных блоков 95% и более по отношению к общему объему виртуального жесткого диска, бэкап первым способом зачастую занимает меньше времени, чем если осуществлять резервное копирование только аллоцированных блоков виртуального жесткого диска.
Давайте добавим новую команду localdumpallocated
, которая опять же сделает копию удаленного виртуального жесткого диска локально, но уже сохраняя только аллоцированные блоки виртуального жесткого диска.
#define LOCAL_DUMP_FILE_MAP "vm_disk_local_dump_map"
typedef std::vector<VixDiskLibBlock> VixDiskAllocatedBlocks;
// Функция получения вектора аллоцированных блоков
static VixDiskAllocatedBlocks DoGetAllocatedBlocksVec();
// Функция сохранения вектора аллоцированных блоков в локальный файл
static void DoLocalDumpBlockFile(const std::string& filename, const VixDiskAllocatedBlocks& allocated_blocks);
static void
DoLocalDumpOneBlock(std::ofstream& output_file, VixDiskLibHandle disk_handle, const VixDiskLibBlock& block) {
const unsigned num_sectors = 1000;
std::vector<uint8> buf(VIXDISKLIB_SECTOR_SIZE * num_sectors);
for (VixDiskLibSectorType i = block.offset; i < block.offset + block.length; i += num_sectors) {
unsigned read_sectors = num_sectors;
if(i + num_sectors > block.offset + block.length) {
read_sectors = block.offset + block.length - i;
}
VixError vixError = VixDiskLib_Read(disk_handle,
i,
read_sectors, buf.data());
CHECK_AND_THROW(vixError);
output_file.write((char*)&buf[0], read_sectors * VIXDISKLIB_SECTOR_SIZE);
}
}
static void
DoLocalDumpAllocated(void) {
const VixDiskAllocatedBlocks allocated_blocks = DoGetAllocatedBlocksVec();
if(!allocated_blocks.empty()) {
std::ofstream output_file(LOCAL_DUMP_FILE, std::ios::out | std::ios::binary);
if(output_file) {
VixDisk disk(appGlobals.connection, appGlobals.diskPaths[0].c_str(), appGlobals.openFlags);
DoLocalDumpBlockFile(LOCAL_DUMP_FILE_MAP, allocated_blocks);
for(unsigned i = 0; i < allocated_blocks.size(); ++i) {
DoLocalDumpOneBlock(output_file, disk.Handle(), allocated_blocks[i]);
}
}
else {
std::cerr<<"Error open file:"<<LOCAL_DUMP_FILE<<endl;
}
}
else {
std::cout<<"No allocated blocks, nothing to dump"<<std::endl;
}
}
В данном коде при передаче программе-примеру команды localdumpallocated
мы вызовем ее обработчик - функцию DoLocalDumpAllocated
.
Внутри этой функции сначала получаем вектор аллоцированных блоков виртуального жесткого диска вызовом функции DoGetAllocatedBlocksVec
, которая является копией оригинальной функции DoGetAllocatedBlocks
- обработчика команды getallocatedblocks. Далее вектор аллоцированных блоков виртуального жесткого диска сохраняется в локальный файл вызовом функции DoLocalDumpBlockFile
. После чего последовательно каждый аллоцированный блок сохраняется в локальный файл через вызов функции DoLocalDumpOneBlock
.
Восстановление
Теперь, когда резервная копия виртуального жесткого диска создана, займемся его восстановлением.
Восстановление виртуального жесткого диска посредством vixDiskLib
предполагает, что мы открываем заранее созданный удаленный виртуальный жесткий диск через vixDiskLib
и записываем содержимое резервной копии в этот открытый удаленный виртуальный жесткий диск. Так как у нас уже есть два вида резервных копий виртуальных жестких дисков - сохраненный целиком виртуальный жесткий диск и только сохраненные аллоцированные области виртуального жесткого диска, - то и процедуры восстановления виртуальных жестких дисков должно быть тоже две, в зависимости от типа резервной копии.
Для простоты будем предполагать, что если в резервной копии существует файл с картой аллоцированных блоков виртуального жесткого диска, то требуется восстановить только эти блоки. Если же файл с картой аллоцированных блоков виртуального жесткого диска не существует в резервной копии, то будем восстанавливать виртуальный жесткий диск целиком.
Далее для краткости рассмотрим восстановление только виртуального жесткого диска, у которого в резервной копии содержатся аллоцированные блоки. Добавим в программу-пример новую команду uploadallocateddisk
и ее обработчик:
// Функция загрузки вектора аллоцированных блоков из локального файла
static VixDiskAllocatedBlocks DoLoadBlockFile(const std::string& filename);
static void
DoUploadOneBlock(std::ifstream& input_file, VixDiskLibHandle disk_handle, const VixDiskLibBlock& block) {
const unsigned num_sectors = 1000;
std::vector<uint8> buf(VIXDISKLIB_SECTOR_SIZE * num_sectors);
for (VixDiskLibSectorType i = block.offset; i < block.offset + block.length; i += num_sectors) {
unsigned write_sectors = num_sectors;
if(i + num_sectors > block.offset + block.length) {
write_sectors = block.offset + block.length - i;
}
if(write_sectors) {
input_file.read((char*)&buf[0], write_sectors * VIXDISKLIB_SECTOR_SIZE);
VixError vixError = VixDiskLib_Write(disk_handle, i, write_sectors, buf.data());
CHECK_AND_THROW(vixError);
}
}
}
static void DoUploadAllocatedlDisk() {
const VixDiskAllocatedBlocks allocated_blocks = DoLoadBlockFile(LOCAL_DUMP_FILE_MAP);
VixDisk disk_to_restore(appGlobals.connection, appGlobals.diskPaths[0].c_str(),
appGlobals.openFlags);
std::ifstream input_file(LOCAL_DUMP_FILE, std::ios::in | std::ios::binary);
if(input_file.is_open()) {
for(unsigned i = 0; i < allocated_blocks.size(); ++i) {
DoUploadOneBlock(input_file, disk_to_restore.Handle(), allocated_blocks[i]);
}
}
else {
std::cerr<<"Unable to open file:"<<LOCAL_DUMP_FILE<<endl;
}
}
В данном коде при передаче нашей программе-примеру команды uploadallocateddisk
будет вызван ее обработчик - функция DoUploadAllocatedlDisk
. Внутри этой функции мы сначала получаем вектор аллоцированных блоков виртуального жесткого из локально сохраненного файла с помощью вызова функции DoLoadBlockFile
. Далее последовательно каждый аллоцированный блок передается в функцию DoUploadOneBlock
, которая считывает его содержимое из локального файла во временный буфер, а затем записывает в удаленный виртуальный жесткий диск посредством вызова функции VixDiskLib_Write
.
Восстановление тонких дисков
В нашей процедуре восстановления есть один недостаток: если изначально виртуальная машина имела тонкий виртуальный жесткий диск, то при восстановлении способами, указанными выше, виртуальная машина получает толстый неаллоцированный диск. Это зачастую не то, что нам нужно.
Что же нам сделать, чтобы при восстановлении получить тонкий виртуальный жесткий диск или диск любого другого доступного типа для записи туда данных из резервной копии? Для начала нам нужно узнать, является ли тонким диск у виртуальной машины, для которой мы создаем резервную копию. Самый простой способ получить такой ответ - это использовать веб-броузер, зайдя на сайт vCenter. У интересующей вас виртуальной машины нажмите ссылку "Редактирование", раскройте выпадающий список с интересующим вас диском и посмотрите значение поля Type. Если диск тонкий, то значение этого поля будет Thin Provision.

Но сделать это можно и с помощью библиотеки vixDiskLib
, используя программу-пример и ее команду meta
. Вывод этой команды будет выглядеть так:
./vix-disklib-sample $VCENTER_PARAMS -vm moref=1111 -meta '[datastore] test_vm/test_vm.vmdk'
Disk[0] "[datastore] test_vm/test_vm.vmdk" is opened using transport mode "nbd".
adapterType = lsilogic
geometry.cylinders = 512
geometry.heads = 128
geometry.sectors = 32
longContentID = 918149eeb8f01751f1ed01f1fffffffe
thinProvisioned = 1
uuid = 60 00 C1 94 bb 39 c1 03-28 e1 ea 9c b1 43 c0 ec
virtualHWVersion = 14
Disk[0] is closed.
Тут нам нужно обратить внимание на наличие поля thinProvisioned
. Если виртуальный жесткий диск создавался как тонкий, то это поле будет присутствовать и его значение будет 1. Если же диск создавался как толстый, то это поле будет отсутствовать.
vixDiskLib
предлагает следующий способ создания тонких дисков на удаленном датасторе:
Создать толстый диск на локальной файловой системе.
Клонировать толстый диск, созданный на шаге 1, на удалённый датастор как тонкий виртуальный жесткий диск.
Загрузить данные из резервной копии на виртуальный жесткий диск, клонированный на шаге 2.
Но почему нельзя исключить в этой последовательности шаг 2 и сразу создать тонкий диск локально? Дело в том, что тонкие диски - это сущность датасторов с файловой системой VMFS
. vixDiskLib
не может создать на локальных файловых системах тонкий виртуальный жесткий диск, как это делает ext4. Важное замечание для тех, кто использует датасторы на основе NFS: этот тип датастора не поддерживает тонкие диски.
Создадим виртуальный жесткий диск локально в файле virtdisk.vmdk
командой ./vix-disklib-sample -create -cap 16384 virtdisk.vmdk
. Размер диска задается параметром -cap в мегабайтах. В данном случае формальный размер диска составит 16 Гб. Но по факту такой файл будет занимать меньше места на файловой системе, что даст нам возможность сэкономить пространство на локальной файловой системе. Такие файлы называются разряженными. Размер диска, переданный ключу cap
, должен быть ровно таким, какой был у виртуального жесткого диска, для которого ранее делалась резервная копия. Также для виртуального жесткого диска по желанию можно задать тип виртуального адаптера параметром -adapter
(ide или scsi, по умолчанию scsi).
Следующим этапом будет клонирование локального виртуального жесткого диска на удаленный датастор.
По умолчанию программа-пример при клонировании использует тип диска VIXDISKLIB_DISK_MONOLITHIC_SPARSE. Для нашей же цели в функции DoClone
программы-примера требуется заменить это значение переменной createParams.diskType
с VIXDISKLIB_DISK_MONOLITHIC_SPARSE на VIXDISKLIB_DISK_VMFS_THIN, чтобы клонировать ранее локально созданный диск как тонкий.
Далее нам нужно осуществить непосредственно клонирование этого диска на удаленный датастор при помощи рассматриваемой программы-примера. Сделать это можно только подключившись напрямую программой-примером на хост гипервизора esxi, на котором находится интересующая нас виртуальная машина. Как и в случае подключения к vCenter, давайте определим отдельную переменную окружения с параметрами подключения к хосту гипервизора esxi:
export ESXI_PARAMS="-host esxi.corp.ru -user root -password 'pa@--w@rD' -thumb AE:6F:AE:61:A2:23:F8:C3:23:B1:78:61:E2:59:12:F8:21:68:71:D4 -vm moref=11 -esxi"
Обратите внимание, что параметр vm
тут соответствует идентификатору виртуальной машины в схеме идентификации данного гипервизора esxi, а не vCenter. По сути это даже не MoRef, так как вначале идентификатора отсутствует префикс vm. Это значение можно получить из адресной строки браузера точно таким же образом, как ранее было получено значение MoRef для виртуальной машины у vCenter, только уже для хоста esxi.
Выполним команду для клонирования локального виртуального жесткого диска как тонкого. Будет передан объем данных, равный размеру изначально созданного локального виртуального жесткого диска:
./vix-disklib-sample $ESXI_PARAMS -vm moref=220 -clone virtdisk.vmdk '[datastore] test_vm/test_vm.vmdk'
Тут также можно указать тип виртуального адаптера клонируемого виртуального жесткого диска.
Теперь удаленный виртуальный жесткий диск, переданный в качестве аргумента, будет иметь тип тонкого диска.
Чтобы в этом убедится, откройте в веб-интерфейсе vCenter свойства виртуального жесткого диска виртуальной машины, для которой выполнялась операция клонирования. По умолчанию там будет отображатся исходный тип виртуального жесткого диска. Отключите этот виртуальный жесткий диск без удаления из датастора от виртуальной машины. Сохраните изменения, откройте снова окно редактирования виртуальной машины и подключите заново к этой же ВМ этот же виртуальный жесткий диск. Вы увидите, что тип виртуального жесткого диска изменился на тонкий и диск получил размер, который был задан при создании локального виртуального жесткого диска командой create
программы-примера. После этого такой виртуальный жесткий диск можно восстановить из резервной копии способом, когда восстанавливаются только аллоцированные блоки виртуального жесткого диска из резервной копии.
Заключение
В этой статье последовательно рассмотрены начальные подходы к резервному копированию и восстановлению виртуальных жестких дисков на платформе VmWare. Начав с получения базовой информации о параметрах виртуальных жестких дисков, мы продолжили созданием процедуры бэкапа удаленного виртуального жесткого диска в локальную файловую систему. Но сам по себе бэкап не имеет смысла без последующего рестора, поэтому мы рассмотрели восстановление тонкого виртуального жесткого диска на удаленный датастор, приняв во внимание ограничения для этой операции.