Скрипт для подсчета места, занимаемого виртуальными машинами Hyper-V

от автора

Недавно я обнаружил расхождение в данных о занимаемом виртуальными машинами дисковом пространстве, отображаемыми в консоли System Center Virtual Machine Manager и полученными при помощи Get-SCVirtualMachine и решил выяснить, в чем дело. Данные о занимаемом дисковом пространстве я получал при помощи распространенного командлета Get-SCVirtualMachine. Для этого я использовал цикл, в котором перебирал все виртуальные машины и накапливал размер их дисков в переменной:

$totalhdd = 0 $vms =  Get-SCVirtualMachine  #| where {$_.Name -eq "VM Name"} # Для отладки  foreach ($vm in $vms) {               $totalhdd += ($vm.VirtualHardDisks.Size -as [double]) / 1TB}   } 

Похожие конструкции многократно тиражируются на форумах technet и во всяких блогах, поэтому сомнений в их корректности у меня не возникало. После обнаружения расхождений я добавил в цикл вывод отладочной информации: $vm.VirtualHardDisks.Size для каждой ВМ и её имя. Вывод измененного скрипта показал, что у некоторых ВМ объём был равен 0. Я был уверен, что $vm.VirtualHardDisks.Size показывает сумму, но это оказалось не так — команда возвращала два числа (для двух vhd). Очевидно, powershell не смог поделить массив на 1TB, поэтому и отдавал 0:

PS D:\Scripts\IT_git> $vm.VirtualHardDisks.Size 3547332608 4194304  PS D:\Scripts\IT_git> ($vm.VirtualHardDisks.Size -as [double]) / 1TB 0 

Даже не знаю в этом случае, сказать спасибо гибкости повершелла за то, что не ERROR, или сказать ему антиспасибо за подобную медвежью услугу. Очень много ошибок прощает.

Тогда я решил перебирать все диски циклом и изменил первоначальную конструкцию на чуть более сложную, но при этом и более корректную:

foreach ($vm in $vms) {        $vhds = $vm.VirtualHardDisks         foreach ($vhd in $vhds) { $totalhdd += ($vhd.Size -as [double]) / 1TB}   } 

Отлично! Теперь ВМ с двумя или более виртуальными дисками считались корректно, НО! Сумма по всем виртуалкам всё равно не совпадала, хоть и приблизилась к показаниям консоли.
Погонял свой скрипт и так, и эдак. Посмотрел, посравнивал и увидел, что по некоторым ВМ сумма совпадает до копейки, а по некоторым наблюдается значительное расхождение. Полез в свойства, а там… снапшоты! Их-то мы и не посчитали.
Далее опять гугл, опять сомнительные скрипты вплоть до очень экзотических методов с поиском файлов по маске.

Скрытый текст

Метод с поиском *avhdx, при этом, в корне неверный, так как в avhd пишутся текущие данные, а снапшот лежит себе в vhdx. Однако, его я встречал и у других авторов

Пришлось писать самому. Сначала я пробовал выбирать все диски при помощи Get-SCVirtualHardDisk не прибегая к перебору виртуальных машин, однако мне удалось перечислять лишь те диски, которые я получал при помощи $vm.VirtualHardDisks. Поэтому пришлось копнуть чуть глубже. У виртуальной машины есть свойство VMCheckpoints, в котором перечислены все контрольные точки. Из этого свойства можно получить, собственно, объект VMSnapshot (я так и не понял чем Snapshot отличается от Checkpoint в терминах SCVMM). У этого объекта также есть свойство VirtualDiskDrives, но у него почему-то нет свойства Size, поэтому пришлось вставить костыль: из VirtualDiskDrives мы берём свойство VirtualHardDiskID и с помощью этого ID делаем Get-SCVirtualHardDisk:

... # Snapshots search     foreach ($vmc in $vm.VMCheckpoints) {         foreach ($vdd in $vmc.VirtualDiskDrives) {             $vhd = Get-SCVirtualHardDisk -ID $vdd.VirtualHardDiskID             $snapshotshdd += ($vhd.Size -as [double]) / 1TB                       }     } ... 

После этого небольшое расхождение всё-таки осталось, и коллега подсказал мне посчитать также служебные файлы .bin и .vsv, в которых хранится служебная информация навроде дампа оперативной памяти. В очередной раз просматривая список доступных параметров виртуальной машины я наткнулся на… $vm.TotalSize. Кто бы мог подумать, что всю работу за меня уже сделали и нужно всего лишь просуммировать этот параметр для всех виртуальных машин!
Вот так через тернии, костыли и грабли я нашёл действительно красивое решение:

$totalhdd = 0 $vms =  Get-SCVirtualMachine  #| where {$_.Name -eq "VM Name"} # Для отладки  foreach ($vm in $vms) {               $totalsize += ($vm.TotalSize  -as [double]) / 1TB   } 

Было так смешно, что решил не удалять из скрипта данные о снапшотах, полученные таким трудом.
Залил вот сюда gallery.technet.microsoft.com/scriptcenter/Script-to-calculate-the-36a9314f

ссылка на оригинал статьи http://habrahabr.ru/post/266097/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *