понедельник, 6 февраля 2017 г.

Пример интеграции VMware vCenter IPAM и Windows IP Address Management

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

Я довольно долго пользовался данным методом выдачи адресов для ВМ в своей лаборатории, однако при всей своей простоте он имеет ряд недостатков. Во-первых, выданные адреса хранятся в текстовом файле, что затрудняет отслеживание свободных адресов и удаление неиспользуемых. Во-вторых, Perl я совсем не знаю, из-за чего крайне затруднительно редактировать скрипт для добавления новых функций.

Поэтому недавно я решил переписать сценарий и интегрировать его со службой Windows IP Address Management, которая присутствует в Windows Server 2012 R2 и более поздних версиях.

Вкратце, выдача адресов работает следующим образом:
  1. При создании ВМ из шаблона, vCenter запускает скрипт на Perl и передает ему XML документ, который содержит информацию о ВМ (имя, расположение, количество сетевых адаптеров и группы портов, к которым они подключены).
  2. Скрипт Perl, в свою очередь, запускает сценарий на Powershell и передает ему XML документ.
  3. Сценарий Powershell подключается к серверу IPAM, запрашивает свободный IP адрес из диапазона, который соответствует группе портов виртуального коммутатора, и резервирует его за ВМ.
  4. Сценарий Powershell возвращает модифицированный XML документ с зарезервированными IP адресами скрипту Perl, который отдает его vCenter.
  5. vCenter использует полученные адреса при создании ВМ.
У данного метода тоже есть ряд недостатков. Скрипт генерирует только IP адрес, маска подсети, маршрутизатор по умолчанию и адрес DNS сервера должны быть прописаны в настройках Customization Specification. Скрипты работают только на vCenter под Windows, т.к. vCenter Server Appliance не поддерживает сценарии на Powershell. Возможно в будущем у меня дойдут руки, чтобы сделать обеспечить работу скрипта и под Appliance.

Ниже приведен пример настройки серверов IPAM и vCenter, а также скрипты на Perl и Powershell.

Настройка

Для начала установите роль IPAM сервера.

Настройте сервер IPAM (Provision the IPAM server). Для хранения конфигурации я использовал встроенную БД и ручной режим настройки политик (Manual).

Создайте новый блок адресов Add IPv4 Address Block. В поле Network ID укажите адрес подсети, задайте маску (Prefix length), начальный и конечный IP адрес блока. Оставьте остальные настройки по умолчанию.

Создайте новую подсеть Address Subnet. В поле Name укажите имя группы портов на виртуальном коммутаторе. В качестве Network ID укажите адрес подсети, укажите маску подсети. Оставьте остальные настройки в значении по умолчанию.

Создайте новый диапазон адресов (Add IP Address Range). В поле Network ID укажите адрес подсети, в поле Prefix length укажите длину маски. В полях Start IP address и End IP address укажите начальный и конечный адрес диапазона для выдачи. Оставьте остальные значения по умолчанию.

Создайте служебную доменную учетную запись, например, Company\IPAMUser.

Назначьте учетной записи роль IP Address Record Administrator Role. Для этого в консоли IPAM перейдите на вкладку ACCESS CONTROL > Access Policies и создайте новую политику (Add Access Policy). В политике в поле User alias укажите имя служебной учетной записи, а поле Access Settings укажите роль и область действия роли (\Global).

На сервере IPAM в консоли управления локальными пользователями и группами добавьте служебную учетную запись в группу "WinRMRemoteWMIUsers_".

На сервере vCenter установите консоль администрирования IPAM (Features > Remote Server Administration Tools > Feature Administration Tools > IP Address Management (IPAM) Client).

Если сервер IPAM и сервер vCenter не являются членами одного домена, и не используется Kerberos аутентификация, то на сервере vCenter вам потребуется добавить сервер IPAM в перечень доверенных серверов, например:
winrm set winrm/config/client @{TrustedHosts="ipam02.company.local"}
или настроить подключение с использованием HTTPS, как описано в статье http://blog.vmpress.org/2009/11/winrm-windows-server-2008.html

На сервере vCenter установите Perl и добавьте параметры в Advanced Settings в настройках vCenter, как это описано в статье http://blog.vmpress.org/2015/06/ip-vmware-vcenter.html

Сохраните скрипт Perl на сервере vCenter, например, в файл "C:\Scripts\wrapper.pl".
use strict;
use warnings;
use MIME::Base64;
use Encode qw(encode);


#Read XML document from STDIN
sub ReadFromSTDIN($) {
my ($fh) = @_;
my $line;
my $doc;
do {
$line = <$fh>;
$doc .= $line;
} while (defined($line) && $line !~ /<\/generator>/);
local $/ = undef;
return $doc;
}

#Write modified XML document to STDOUT
sub WriteToSTDOUT($$) {
my ($fh, $doc) = @_;
print $fh $doc;
}

#Encode XML document to Base64 format
sub EncodeXML($) {
my ($doc) = @_;
my $encoded = encode_base64(encode("UTF-8", $doc));
$encoded =~ s/[\x0A\x0D]//g;
return $encoded;
}

# Main
eval {
my $doc = ReadFromSTDIN(\*STDIN);
my $encoded = EncodeXML($doc);
my $result = `"powershell.exe -file C:\\scripts\\ipam.ps1 $encoded"`;
WriteToSTDOUT(\*STDOUT, $result);
exit(0);
}
При необходимости отредактируйте путь к сценарию Powershell, не забудьте про экранирование символа "\" в пути.

Сохраните сценарий Powershell на сервере vCenter, например, в файл "C:\scripts\ipam.ps1".
param (
[string]$InputString
)

#Return credetials to connect to IPAM server
function generate-Credentials($Username, $Password) {
$Pass = ConvertTo-SecureString -String $Password -AsPlainText -Force
$Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $Pass
return $Cred
}

#If hostname is empty, set hostname = VM name
function generate-VMName($xml) {
$LastIndexOf = $xml.generator.vm.LastIndexOf("/")
$VMName = $xml.generator.vm.Substring($LastIndexOf+1)
if($xml.generator.hostname -eq "") {
$xml.generator.hostname = $VMName
}
return $xml
}

#Request free IP address from IPAM Subnet name equal to NIC's virtual switch port group
function get-IPAddress ($CimSession, $SubnetName) {
$IPAddress = (get-ipamsubnet -addressfamily ipv4 -cimsession $CimSession | where {$_.Name -eq $SubnetName} | get-ipamrange -addressfamily ipv4 | find-ipamfreeaddress).ipaddress
return $IPAddress
}

#Convert Base64 string to XML document
[xml]$xml = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($InputString))

#IPAM server address, username and password
$IpamServer = "ipam02.company.local"
$Username = "COMPANY\IPAMUser"
$Password = "P@ssw0rd"
$Credentials = generate-Credentials $Username $Password
$xml = generate-VMName $xml
$CimSession = New-CimSession -ComputerName $IpamServer -Credential $Credentials

#Request and assign IP addresses for all NICs
foreach ($element in $xml.generator.nics) {
$SubnetName = $element.nic.Network
$ipaddress = get-IPAddress $CimSession $SubnetName
#Reserve IP address from IPAM and write it to XML document
if($ipaddress) {
Add-IpamAddress -IpAddress $ipaddress -AssignmentType auto -devicetype VM -devicename $xml.generator.hostname 

-MacAddress $element.nic.macaddress -CimSession $CimSession
$element.nic.ipaddress = $ipaddress.ToString()
}
}
return $xml.InnerXml
В сценарии Powershell задайте адрес сервера IPAM и укажите имя и пароль служебной учетной записи.

Отредактируйте параметры в Advanced Settings в настройках vCenter, указав путь к исполняемому файлу Perl и скрипту.
В параметре config.guestcust.name-ip-generator.arg1 укажите путь к скрипту "C:\scripts\wrapper.pl".
В параметре config.guestcust.name-ip-generator.arg2 укажите путь к скрипту "C:\scripts\wrapper.pl".
В параметре config.guestcust.name-ip-generator.program укажите путь к исполняемому файлу "C:\Perl64\Bin\perl.exe".

Создайте или отредактируйте существующие настройки Customization Specification на сервере vCenter. На вкладке Configure Network выберите ручной вариант настройки адресации (Manually select custom settings) и отредактируйте настройки виртуального сетевого адаптера.

На вкладке IPv4 выберите вариант Use an application configure on the vCenter Server to generate an IP address, задайте маску подсети (Subnet Mask) и маршрутизатор по умолчанию (Default Gateway). На вкладке DNS укажите адрес DNS сервера.

На этом настройка завершена.

Проверка работы

Для проверки работы скрипта запустите его в ручном режиме из командной строки.
С:\Perl64\bin\perl.exe c:\scripts\wrapper.pl
и используйте тестовый XML документ, например:
<generator>
     <datacenter>/New Datacenter</datacenter>
     <vm>/New Datacenter/vm/New Virtual Machine</vm>
     <vm-moref>vim.VirtualMachine:vm-249</vm-moref>
     <hostname/>
     <uuid>502081ef-91df-7455-e570-be1f6d4f5abc</uuid>
     <guest>winXPProGuest</guest>
     <nics>
        <nic id="0">
           <ipaddress/>
           <iparg></iparg>
           <macaddress>00:50:56:a0:70:15</macaddress>
           <network>VM Network</network>
        </nic>
     </nics>
</generator>
Если все настроено корректно, то в результате работы скрипта вы увидите XML со сгенерированным IP адресом.

А на сервере IPAM появится информация о выданном IP адресе.

После проверки на тестовом XML можно попробовать создать ВМ из шаблона.