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

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

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

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


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

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

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

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

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

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

При первом запуске ОС из шаблона на ней должен выполниться скрипт первоначальной настройки. Для хранения этого скрипта 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. Завершите работу ОС.

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

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

  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.
    2. Конвертируйте файл диска ВМ в формат RAW: 

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

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

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

  • LVM:
    1. Подключитесь к узлу кластера VMmanager по 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

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


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

Файл скрипта должен быть сохранён в формате 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

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


Файл метаданных 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> — имя файла образа;
  • <rebootcount> — количество перезагрузок, после которого VMmanager будет считать, что ОС установлена;
  • <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>
  <rebootcount>1</rebootcount>
  <type>ostemplate</type>
  <installdrive>windows.cmd</installdrive>
  <virtiodisk>yes</virtiodisk>
  <virtionet>yes</virtionet>
  <macro>
    <elem name="($PRODUCTKEY)"/>
  </macro>
</doc>
CODE

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


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

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