Шаблон ОС Windows для репозитория должен содержать:

  • образ диска ОС;
  • скрипт первоначальной настройки;
  • файл с метаданными.

Статья описывает этапы подготовки шаблона.

Образ диска ОСLink to Образ диска ОС


Подготовка образаLink to Подготовка образа

Для подготовки образа вы можете:

  • установить нужную версию ОС Windows на физический сервер;
  • использовать ВМ в платформе.

Чтобы подготовить образ из ВМ:

  1. Создайте ВМ без операционной системы.
  2. Измените тип подключения диска ВМ на IDE: раздел Виртуальные машины → выберите ВМ → кнопка Параметры → раздел Виртуальные диски → меню Редактировать диск → выберите Тип подключения ide → кнопка Изменить и перезапустить.
  3. Установите на ВМ ОС Windows из ISO-образа. После установки ОС отключите ISO-образ. Подробнее о работе с ISO-образами см. Подключение ISO-образа.
  4. Чтобы подготовить ВМ к установке драйверов virtio, создайте диск размером 1 ГБ с типом подключения virtio и подключите его к ВМ: раздел Виртуальные машины → выберите ВМ → кнопка Параметры → раздел Виртуальные диски Подключить еще дискСоздать диск и подключить → выберите Размер 1 ГБ и Тип подключения virtio → кнопка Подключить диск.
  5. Скачайте и установите на ВМ драйверы Virtio.
  6. Скачайте и установите на ВМ ПО QEMU Guest Agent.
  7. Измените тип подключения основного диска ВМ на Virtio: раздел Виртуальные машины → выберите ВМ → кнопка Параметры → раздел Виртуальные диски → меню Редактировать диск → выберите Тип подключения virtio → кнопка Изменить и перезапустить.
  8. Подключитесь к ВМ по VNC или SPICE и проверьте, что всё оборудование в диспетчере устройств установлено корректно.

Настройка образаLink to Настройка образа

При первом запуске ОС из шаблона на ней должен выполниться скрипт первоначальной настройки. Для хранения этого скрипта VMmanager создаёт отдельный виртуальный диск. Загрузка скрипта с виртуального диска осуществляется с помощью утилиты dd. Чтобы настроить запуск скрипта:

  1. Создайте в ОС директорию C:\vmmgr\.
  2. Создайте в директории C:\vmmgr\ скрипты firstrun.cmd, firstrun.ps1, ddwrap.cmd:

    Файлы скриптов должны быть в формате Windows. Переводы строк должны выполняться с помощью управлящих символов CR LF.

    firstrun.cmd

    @echo off
    powershell.exe C:\vmmgr\firstrun.ps1 >NUL
    CODE

    firstrun.ps1

    $ddout = C:\vmmgr\ddwrap.cmd
    $ddout
    $list = $ddout | select-string "size is 1048576 bytes" -Context 3,0
    $list
    $context = $list.Context.PreContext | select-string Part
    $str = $context.Line
    $str
    C:\vmmgr\dd.exe if=$str of=C:\vmmgr\vmmgr.cmd bs=512 count=2048
    C:\vmmgr\vmmgr.cmd
    CODE

    ddwrap.cmd

    c:\vmmgr\dd.exe --list 2>&1
    CODE
  3. Скачайте утилиту dd, распакуйте архив и скопируйте файл dd.exe в директорию C:\vmmgr\ .
  4. Разрешите в PowerShell выполнение неподписанных скриптов. Для этого зайдите в PowerShell и выполните команду:

    Set-ExecutionPolicy RemoteSigned
    BASH
  5. Добавьте скрипт C:\vmmgr\firstrun.cmd в автозагрузку. Для этого создайте в планировщике задание с именем vmmgr_firstrun, которое нужно выполнить при запуске системы. Включите для задания параметр безопасности "Выполнять вне зависимости от регистрации пользователя".
  6. Завершите работу ОС.

Создание образаLink to Создание образа

Если вы подготовили образ на физическом сервере:

  1. Загрузитесь с любого Live CD.
  2. Cоздайте образ диска ОС. Это можно сделать с помощью утилиты dd или virt-sparsify.

    Пример создания образа с помощью dd

    dd.exe if=\\?\Device\Harddisk0\DR0 of=c:\vmmgr\tempdisk1.img bs=8M
    CODE

     if — путь к диску с ОС. Список можно посмотреть командой "dd --list"

    of — путь к выходному файлу образа

    bs — размер блока в мегабайтах (M) или килобайтах (k)

    Пример создания образа с помощью virt-sparsify

    virt-sparsify /path/to/device disk.img
    BASH

    /path/to/device — путь к диску с ОС

    disk.img — выходной файл образа

Если вы подготовили образ с помощью VMmanager, порядок создания образа зависит от типа хранилища:

  • файловое, NAS:
    1. Подключитесь к узлу кластера VMmanager по SSH. Подробнее о подключении по SSH см. в статье Настройка рабочего места.
    2. Конвертируйте файл диска ВМ в формат RAW: 

      qemu-img convert -f qcow2 -O raw <qcow_input> <raw_output> 
      BASH

      <qcow_input> — исходный файл в формате Qcow2

      <raw_output> — выходной файл в формате RAW

  • LVM:
    1. Подключитесь к узлу кластера VMmanager по SSH. Подробнее о подключении по SSH см. в статье Настройка рабочего места.
    2. Экспортируйте файл диска ВМ: 

      qemu-img convert -f raw -O raw <path_to_vm/raw_input> <raw_output>
      BASH

      <path_to_vm/raw_input> — путь и имя исходного файла диска ВМ в формате RAW

      <raw_output> — выходной файл в формате RAW

  • Ceph:
    1. Подключитесь к серверу-монитору Ceph с исходной ВМ.

    2. Экспортируйте файл диска ВМ:  

      rbd export <pool_name>/<disk_name> <raw_output>
      BASH

      <pool_name> — имя пула Ceph

      <disk_name> — имя диска ВМ

      <raw_output> — выходной файл в формате RAW

Скрипт первоначальной настройкиLink to Скрипт первоначальной настройки


Для первоначальной настройки ОС вы можете использовать скрипт, приведённый ниже. Чтобы включить русский язык в настройках ОС, раскомментируйте строки 117-125.

Если скрипт первоначальной настройки определён в файле metadata.json из репозитория шаблонов, то скрипт из шаблона ОС не будет использоваться. Подробнее см. в статье Репозитории.

Файл скрипта должен быть сохранён в формате Windows. Переводы строк должны выполняться с помощью управлящих символов CR LF.

windows.cmd

@echo off
setlocal EnableDelayedExpansion

set logfile=C:\setup.log

del /f c:\ifacename.txt

for /f "skip=2 tokens=2,4*" %%A in ('netsh interface show interface') do (
  if "%%A" == "Connected" (
    echo %%B %%C>> c:\ifacename.txt
  )
)

set /P IFACENAME=< c:\ifacename.txt

echo Trimming

set IFACENAME=%IFACENAME%##
set IFACENAME=%IFACENAME:    ##=##%
set IFACENAME=%IFACENAME:  ##=##%
set IFACENAME=%IFACENAME: ##=##%
set IFACENAME=%IFACENAME:##=%

del /f c:\ifacename.txt

echo --- Interface name: %IFACENAME% >> %logfile%

echo --- set Administartor password >> %logfile%

net user Administrator ($PASS)  >> %logfile%
echo ------Set static IP-------------------------------------[%DATE%-%TIME%]      > %logfile%
echo --- IP/NM=($IP)/($NETMASK)  GW=($GATEWAY)      >> %logfile%
echo --- NS1=($NAMESERVER)                                                   >> %logfile%

set "nexthop=($NEXTHOPIPv4)"

IF "%nexthop%"=="()" (
        set "nexthop=NONE"
)
echo %nexthop% | findstr /c:( 1>nul
IF NOT ERRORLEVEL 1 (
        set "nexthop=NONE"
)

IF (%nexthop%) == () (
        set "nexthop=NONE"
)

if (%nexthop%) == (NONE) (
        netsh interface ip set address    "%IFACENAME%" static ($IP) ($NETMASK) ($GATEWAY)  >> %logfile%
) ELSE (
        netsh interface ip set address    "%IFACENAME%" static ($IP) 255.255.255.255 ($NEXTHOPIPv4)  >> %logfile%
)

netsh interface ip add dnsservers "%IFACENAME%" ($NAMESERVER)          >> %logfile%

set "nslist=($NAMESERVERS)"

IF "%nslist%"=="()" (
        set "nslist=NEX"
)
echo %nslist% | findstr /c:( 1>nul
IF NOT ERRORLEVEL 1 (
        set "nslist=NEX"
)

if NOT "%nslist%"=="" ( 
        IF NOT "%nslist%"=="NEX" (
                set flist=%nslist:"=%
                echo NAMESERVERS: !flist! >> %logfile%
REM                netsh interface ip delete dnsservers "%IFACENAME%" all >> %logfile%
                FOR %%i IN (!flist!) DO (
                        echo %%i >> %logfile%
                        echo %%i | findstr /c:: 1>nul
                        if ERRORLEVEL 1 (
                                echo ipv4 >> %logfile%
                                netsh interface ip add dnsservers "%IFACENAME%" %%i >> %logfile%
                        ) ELSE (Related topics                                 echo ipv6 >> %logfile%
                                netsh interface ipv6 add dnsservers "Ethernet" %%i >> %logfile%
                        )
                )
        ) ELSE (
                echo BRACERS >> %logfile%
        )
) ELSE (
        echo EMPTY >> %logfile%
)

set extendfile=C:\vmmgr\extend.txt
echo --- resize disk >> %logfile%
echo select volume 1 > %extendfile%
echo extend noerr >> %extendfile%
diskpart.exe /s %extendfile% >> %logfile%

set "pkey=($PRODUCTKEY)"

IF NOT "%pkey%" == "" (
        IF NOT "%pkey%" == "()" (
                echo "PKEY is not null. Activating license"
                echo activate windows >> %logfile%
                cscript %windir%\system32\slmgr.vbs -ipk %pkey%
                cscript %windir%\system32\slmgr.vbs -ato
        ) ELSE (
                echo "PKEY is bracers" >> %logfile%
        )
) ELSE (
        echo "PKEY is EMPTY" >> %logfile%
)

echo remove task vmmgr_firstrun >> %logfile%
schtasks /Delete /TN "vmmgr_firstrun" /F  >> %logfile%
echo restart OS >> %logfile%
echo ------END--------------------------------------------------[%DATE%-%TIME%]     >> %logfile%

REM Russian language
REM echo $lang = "ru-RU" >> C:\vmmgr\lang.ps1
REM echo $langpack = Get-ChildItem "C:\vmmgr\langs\*language*$lang.cab" >> \vmmgr\lang.ps1
REM echo Dism /Online /Add-Package /PackagePath:"$langpack" >> C:\vmmgr\lang.ps1
REM echo Set-WinSystemLocale $lang >> c:\vmmgr\lang.ps1
REM echo Set-WinUILanguageOverride $lang >> c:\vmmgr\lang.ps1
REM echo $oldList = Get-WinUserLanguageList >> c:\vmmgr\lang.ps1
REM echo $oldList.Add($lang) >> c:\vmmgr\lang.ps1
REM echo Set-WinUserLanguageList $oldList -force >> c:\vmmgr\lang.ps1
REM powershell.exe c:\vmmgr\lang.ps1 >> %logfile%

REM Enable RDP
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
netsh firewall set service remotedesktop enable

echo RMDIR /s /Q  C:\vmmgr >> c:\del.cmd
echo shutdown /r >> c:\del.cmd
cmd /c c:\del.cmd
BASH

Файл с метаданнымиLink to Файл с метаданными


Файл метаданных metainfo.xml содержит информацию о шаблоне:

  • <osname> — название ОС;
  • <limit> — ограничения шаблона. Если ВМ не удовлетворяет ограничениям, то она не будет создана. Параметры ограничений:
    • <elem name="ipv4"> — использование IPv4-адреса в качестве основного. Возможные значения: yes — поддерживается, no — не поддерживается;
    • <elem name="ipv6"> — использование IPv6-адреса в качестве основного. Возможные значения: yes — поддерживается, no — не поддерживается;
    • <elem name="mem"> — минимальный объём RAM в МиБ;
    • <elem name="disk"> — минимальный объём дискового пространства в МБ;
  • <support> — ПО, которое поддерживает шаблон. Для VMmanager укажите <elem>VMmgr</elem>;
  • <tags> — теги шаблона. Используются для совместимости со скриптами;
  • <version> — версия шаблона;
  • <hddimage> — имя файла образа;
  • <type> — тип шаблона. Для шаблона ОС укажите <type>ostemplate</type>;
  • <installdrive> — имя скрипта первоначальной настройки;
  • <virtionet>yes</virtionet> — поддержка работы с virtio-сетью;
  • <virtiodisk>yes</virtiodisk> — поддержка работы с virtio-дисками;
  • <macro> — макросы для передачи в шаблон. Для передачи значения лицензионного ключа укажите <elem name="($PRODUCTKEY)"/>.

Пример файла metainfo.xml

<?xml version="1.0"?>
<doc>
  <osname>Windows-Server-2019</osname>
  <limit>
    <elem name="ipv4">yes</elem>
    <elem name="ipv6">no</elem>
    <elem name="mem">1024</elem>
    <elem name="disk">15000</elem>
  </limit>
  <support>
    <elem>VMmgr</elem>
  </support>
  <tags>windows,windows2019</tags>
  <version>5</version>
  <hddimage>win2019.hddimage</hddimage>
  <type>ostemplate</type>
  <installdrive>windows.cmd</installdrive>
  <virtiodisk>yes</virtiodisk>
  <virtionet>yes</virtionet>
  <macro>
    <elem name="($PRODUCTKEY)"/>
  </macro>
</doc>
CODE

Загрузка шаблона в репозиторийLink to Загрузка шаблона в репозиторий


Чтобы загрузить шаблон:

  1. Создайте архив формата .tar.gz, включающий образ диска ОС, скрипт первоначальной настройки и файл с метаданными.
  2. Скопируйте архив в директорию репозитория.
  3. Добавьте информацию о шаблоне в файл описания репозитория metadata.json. Подробнее см. в статье Репозитории.