Автоматическое разворачивание виртуальных машин с помощью шаблона в VMware
Сразу сделаю громкое заявление, я ленивый, очень, страшно! И поэтому на работе, столкнувшись с необходимостью разворачивания ВМ с шаблона, по 12-20 в неделю, я задумался написать скрипт. Признаюсь, мои коллеги уже имели скрипт в PowerShell, который это делает, но он был на столько... эм... не знаю, как сказать, в общем, нужно было информацию по каждой ВМ вписывать вручную, диски не мапятся, сетевые карты не добавляются, с ядерностью проца - траблы, и т.д.
Решил я его переделать, автоматизировать, так сказать )))
Для начала, нужно установить модуль PowerShell для VMware - PowerCLI.
Здесь есть полезная инфа, как и чего.
Доступные командлеты с описанием и примерами
Обратите внимание, что существуют ограничения для командлетов "в релизе", некоторые из них работают ТОЛЬКО в 4й версии VSphere, другие - только в 5й. Скрипт, который предоставлен ниже, работает только с 5й и выше версиями, так как в нём используются соответствующие командлеты.
Скрипт скрипт использует сессии к серверу, где установлен VMware VCenter. Скрипт использует CSV файл для работы, так как названия серверов, датацентров, пути к определённой папке, названия шаблонов - всегда будет где-то ошибка.
Структура CSV файла выглядит так:
- VMName - Имя, которое должно быть присвоено ВМ.
- VMTemplateName - Имя шаблона, с которого будет разворачиваться ВМ.
- VCenterHostName - Имя сервера, на котором установлен VCenter, указан потому, что на каждый датацентр (физический, а не VMware) существует свой VCenter сервер, а в файле можно указать ВМ для разных датацентров.
- VSphereCluster - Кластер VSphere, к которому проводится подключение после подключения к VCenter серверу.
- VSphereResPool - ресурсный пул для ВМ, если ресурсы датацентра поделены на несколько "ярусов", например, по производительности платформы в случае использования разных серверов (старых и новых) или дисков - SSD или SATA (для БД это критично).
- VSphereDataStore - датастор для ВМ, указывается хранилище данных, где "физически" будет располагаться ВМ.
- VSphereFolder - каталог, в котором должна находиться ВМ. Тут путь выглядит в формате "DC2-Cloud PROD Tier|Wintel TEST & DEV|Project BI", так как в VMware у нас может быть несколько каталогов с одинаковым именем, только по разным адресам. К сожалению, указать полный путь к нужному каталогу не получится, параметр ввода каталога - имя, либо ID, который у всех каталогов уникальный. Для определения этого ID был написана функция, которая ищет необходимый нам каталог по заданному адресу (был подан в отдельной статье ранее). Разделение каталогов в строке пути - "|", так как "\" - служебный символ в PowerShell и его нужно экранировать, а это дополнительное баловство с синтаксисом и повышение вероятности ошибки.
- VMSocket - Кол-во сокетов для ВМ.
- VMCore - Кол-во ядер для ВМ.
- VMRAM - тут понятно, но всё же, кол-во ОЗУ в ГБ.
- VMHDD - если указано число, отличное от нуля - добавляет ещё один диск (не для системы) с указанным объёмом, так как в настройках шаблона уже должен быть указан системный диск и его объём.
- VMNetworks - указывает VLAN-ы сетевых карт. Подаётся в формате "387|388|389", где каждое число - это уникальное значение VLAN-a, так как имя VLAN-а создаётся согласно определённому шаблону, например "DC2N-MGMT-VLAN387" или "DC2N-PROD-VLAN389". Разделители - "|", для того, чтобы скрипт понимал кол-во сетевых карт и куда их подключить. Плодить дополнительные столбцы в CSV при отутствии ограничения максимального кол-ва сетевых карт - неправильно.
- OSCustomizationSpec - Спецификация кастомизации - политика разворачивания шаблона, в которой указаны основные настройки ВМ после установки, например, размер системного диска, кол-во COM-портов или генерирование нового SID-а для ВМ.
По ходу скрипта будут сделаны замечания, как/почему это сделано.
param
(
[string]$csvFile = $(throw "-csv file path is required.")
)
# статическое указание файла конфигурации (закомментировано).
#$csvFile = "D:\Script\VMDeploy.csv"
# проверка на существование файла, если его нет (в имени ошибка) - прерывание выполнения скрипта
if(Test-Path -Path $csvFile)
{
$VMCSV = Import-Csv -Path $csvFile
}
else
{
Write-Host "CSV file not found"
exit
}
# выполняем действия для каждой ВМ:
foreach($VMArray in $VMCSV) # for each line in CSV
{
# начало блока скрипта, который позже будет выслан на сервер VCenter
$script = {
param($VMArray) # считывание параметров CSV файла
# проверка возможности загрузки модуля PowerCLI, в случае ошибки - переход к следующей ВМ
Get-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -ErrorVariable PSError
if($PSError)
{
Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -ErrorVariable SnapInError
if($SnapInError)
{
"VMware.VimAutomation.Core could not be loaded by the reason $SnapInError"
Exit
}
}
# установка конфигурации работы PowerCLI, необходимая вещь!
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -InvalidCertificateAction Ignore -DisplayDeprecationWarnings:$false -Confirm:$false
#подключение к VCenter серверу
$vSphere_Connection = Connect-VIServer -Server $VMArray[0].VCenterHostName
"Connection to $vSphere_Connection has been established."
# проверка на существование необходимой ВМ, чтобы не пытаться создать с уже занятым именем. В случае наличия ВМ - переход к созданию новой ВМ.
if(Get-VM -Name $VMArray[0].VMName -ErrorAction SilentlyContinue -ErrorVariable CheckVmExists)
{
$VMArray[0].VMName + " already exists."
}
# если нет ВМ с заданым именем:
else
{
# подключаемся к кластеру
$vSphereCluster = Get-Cluster -Name $VMArray[0].VSphereCluster # get the necessary cluster
"$vSphereCluster connected."
# получаем данные ресурсного пула, чтобы потом его указать при создании ВМ
$vSphereResPool = Get-ResourcePool -Name $VMArray[0].VSphereResPool -Location $vSphereCluster # get the necessary resource pool
"$vSphereResPool state."
# указываем путь к каталогу ВМ и начинаем поиск указанного каталога, в переменную записывается ИД необходимого каталога. В случае, если данный каталог не найден - указывается ИД корневого каталога, ВМ можно перенести вручную.
$Path = ($VMArray[0].VSphereFolder).Split("|") # split the folder pass into array to find the final folder
$vSphere_Datacenter = Get-Inventory -Location (Get-Folder -Name Datacenters -NoRecursion) -NoRecursion # Start from the root - datacenter
$VMFolder = Get-Inventory -Location $vSphere_Datacenter -NoRecursion | where {$_.type -eq "VM"} # get all folders in datacenter and capture the folder for VMs
# поиск каталога
for($i=0; $i -lt $Path.Count; $i++) # for each folder in the path - check if exist the next hop folder
{
if((Get-Inventory -Location $VMFolder -NoRecursion | select -ExpandProperty Name) -contains (($Path[$i]).Trim()))
{
$VMFolder = Get-Inventory -Name $Path[$i] -Location $VMFolder -NoRecursion
}
# если каталог не найден
else
{
$VMFolder = Get-Inventory -Location $vSphere_Datacenter -NoRecursion | where {$_.type -eq "VM"}
"Break VMFolder " + $VMFolder
break
}
}
# проверка на доступность хранилища, куда будет "положена" или "покладена" ВМ если датастор не доступен - переход к следующей ВМ
if ((Get-Datastore -Name $VMArray[0].VSphereDataStore).State -ne "Available")
{
"There is no Datastore name "+ $VMArray[0].VSphereDataStore + " to accomodate this Vm: "+ $VMArray[0].VMName
}
# если датастор доступен - создание ВМ с указанием почти всех параметров. Некоторые параметры используются после создания ВМ.
else
{
New-VM -Name $VMArray[0].VMName -Location $VMFolder -Template $VMArray[0].VMTemplateName -ResourcePool $vSphereCluster -DataStore $VMArray[0].VSphereDataStore -OSCustomizationSpec $VMArray[0].OSCustomizationSpec -ErrorVariable VMError
if($VMError)
{
# в случае ошибки при создании - вывести ошибку
$VMError
}
else
{
# если ВМ создана, то перемещаем ВМ в ресоурс пул, который нам указан. У VMware есть проблема, при создании они просят указать кластер, но называют это "ресоурс пул", а параметра для ресоурс пула нет, поэтому ВМ создаётся в ресоурс пуле по умолчанию, а потом - переносится в необходимый.
$VMArray[0].VMName + " moving to " + $VMArray[0].VSphereResPool
Move-VM -VM $VMArray[0].VMName -Destination $VMArray[0].VSphereResPool
# изменение ОЗУ
"RAM: " + ([int]$VMArray[0].VMRAM) + " CPU " + ([int]$VMArray[0].VMSocket)
Set-VM -VM $VMArray[0].VMName -MemoryGB ([int]$VMArray[0].VMRAM) -NumCpu ([int]$VMArray[0].VMSocket) -Confirm:$false
# VMware из PowerShell позволяет только изменить кол-во сокетов, а кол-во ядер - нет. Поэтому, пришлось делать вручную
"Cores per socket " + ([int]$VMArray[0].VMSocket)
$TempSpec = New-Object -Type VMware.Vim.VirtualMachineConfigSpec -Property @{"NumCoresPerSocket"=([int]$VMArray[0].VMSocket);"numCPUs"=([int]$VMArray[0].VMSocket * [int]$VMArray[0].VMCore)}
"numCPUs = " + ([int]$VMArray[0].VMSocket * [int]$VMArray[0].VMCore)
(Get-VM $VMArray[0].VMName).ExtensionData.ReconfigVM_Task($TempSpec)
#добавление жёсткого диска, в случае необходимости (если указано число больше ноля)
"HDD " + [int]$VMArray[0].VMHDD
if([int]$VMArray[0].VMHDD -ne "0")
{
New-HardDisk -VM $VMArray[0].VMName -CapacityGB ([int]$VMArray[0].VMHDD) -StorageFormat Thick
}
# так как мне нехотелось получать ИД созданной сетевой карты, а потом менять VLAN (там тоже свои проблемы при определении параметров командлета), я решил её просто удалить и создать новую ))))
Get-NetworkAdapter -VM $VMArray[0].VMName | Remove-NetworkAdapter -Confirm:$false
"VMNetworks " + ($VMArray[0].VMNetworks).Split("|")
# создание новых сетевых карт с подключением к необходимому VLAN-у. Нужно было бы провести проверку на существование VLAN-а, при неправильном указании имени, но лень ))) так что, смотрите в оба!
foreach($VLAN in (($VMArray[0].VMNetworks).Split("|")))
{
$VLAN = (Get-VirtualPortGroup | Where-Object {($_.Name -Match ("VLAN" + $VLAN))}).Name
"Adding VLAN: " + $VLAN
New-NetworkAdapter -NetworkName $VLAN -VM $VMArray[0].VMName -Type e1000
}
# включение сетевых карт при включении ВМ
"Set all NICs to Conect at Power On."
Get-NetworkAdapter -VM $VMArray[0].VMName | Set-NetworkAdapter -StartConnected:$true -Confirm:$false
}
}
}
# отключение от VCenter сервера
Disconnect-VIServer -Server $vSphere_Connection -Confirm:$false
}
# старт удалённой сессии на VCenter сервер
$session = New-PsSession -ComputerName $VMArray[0].VCenterHostName
# передача блока скрипта на выполнение
Invoke-Command -Session $session -ScriptBlock $script -ArgumentList (,$VMArray)
# завершение сессии - ОБЯЗАТЕЛЬНО!
Remove-PSSession -Session $session
}
Стоит заметить, что VSphere у каждого настроен по своему, и для Вас необходимо будет, скорее всего, менять некоторые параметры. Но сути это не меняет, ВМ может быть создана автоматически за 5 минут, либо будете кликать мышкой более 20.
Во вложении пример CSV файла и скрипт без моих комментариев
Особая благодарность Mateusz Skrzynski за помощь при написании скрипта.
Прикрепленный файл | Размер |
---|---|
DeployWinVM.zip | 2.56 кб |
- Войдите на сайт для отправки комментариев
- Версия для печати