Автор: DevOps Team Leader компании Hostkey Егор Гараджа В прошлой статье мы рассказали, как нам удалось решить проблему установки Windows и Linux через Foreman в Legacy-режиме (BIOS/MBR). Другой важной задачей стала поддержка инсталляций в режиме EFI. В случае Foreman этот вопрос решается через использование отдельного загрузчика. Для Linux наш выбор пал на Grub2, и реализация загрузки оказалась достаточно тривиальной — нами была создана конфигурация Grub для загрузки initrd и ядра. В случае с Windows ситуация сложнее. Изначально загрузка Windows осуществлялась через расширение для iPXE. Проблема, однако, в том, что это расширение, как и многие другие (memdisk и т. п.), не поддерживалось официально для EFI-версии загрузчика. Кнечно, можно попытаться решить этот вопрос самостоятельными правками и сборкой нужных модулей, но мы в целом хотели уйти от iPXE, поскольку это не совсем честный pxe-загрузчик, а скорее мини-операционная система со своими драйверами для сетевых карт, что изредка создавало проблемы при инсталляциях. Мы сделали попытку использовать модуль Grub2, позволяющий смонтировать по http образ диска и загрузиться с него. Этот вариант не сработал, так как производительность модуля при работе по сети оказалась очень низкой, не говоря уже о стабильности. В результате изучения вопроса мы пришли к следующим вариантам решения проблемы: Создание процедуры инсталляции, в которой на первом шаге используется Linux, а дальнейшая инсталляция происходит с использованием WindowsPE, без изменений относительно механизма Legacy-установки через iPXE. Встраивание поддержки загрузчика Microsoft в Foreman (потребуется модификация файла /usr/share/foreman/app/models/concerns/pxe_loader_support.rb из поставки Foreman для добавления загрузчика в его меню). Создание инсталляции из шаблонов (аналогично Fog Project) с использованием Microsoft sysprep целиком из Linux, без родного инсталлятора. Мы попробовали разные варианты, но в этой статье мы хотим рассказать о первом, поскольку сейчас он является основным в нашей инфраструктуре и хорошо испытан. Главный плюс этого подхода — это расширение к существующей процедуре установки ,а потому  не требует поддерживать различную конфигурацию для режимов EFI и Legacy. Главной проблемой стала архитектурная избыточность — не вся ОС ставится через Linux LiveCD, а лишь WindowsPE, что приводит к лишним шагам и потенциальным точкам отказа. Установка будет проходить через следующие этапы: Штатная загрузка Linux LiveCD через PXE Grub2. Скрипт установки Linux должен: произвести разбивку диска для EFI и WindowsPE; загрузить WindowsPE и организовать его EFI-загрузку с диска; загрузить все необходимые скрипты и шаблоны с Foreman для установки Windows; сообщить Foreman о завершении установки, в результате чего следующая загрузка произойдет с диска, то есть загрузится WindowsPE. Далее установка должна пройти штатно — аналогично legacy-режиму, где сразу грузится WindowsPE. Темплейт Grub2 загружает штатный LiveCD, сборку которого мы описывали в предыдущей статье. Параметры systemd.setenv позволяют пробросить в загруженную систему ряд переменных окружений, благодаря чему можно запустить конкретный скрипт для последующей инсталляции и задать ему параметры для получения с Foreman шаблонов. В systemd LiveCD добавляется сервис, который стартует только в том случае, если SPEEDISO=peinstall. Подробнее мы рассказывали об этом в одной из прошлых статей. Стартовый скрипт выполняет основную магию: выбирает INST_DRIVE среди имеющихся в системе по указанной администратором логике, а затем производит следующие операции: # Создает, с помощью parted, раздел ESP размером 1 гигабайт в начале диска: # Подготавливает директории для монтирования файловых систем: # Загружает WindowsPE ISO с зеркала с помощью wget и монтирует его (вместо загрузки можно воспользоваться функционалом Fuse и сразу приступить к монтированию):   # Подключает EFI-партицию и отправляет туда содержимое WindowsPE ISO, а также EFI-загрузчик Microsoft (мы держим его прямо на LiveCD, но можно закидывать через сеть. Он лежит в директории EFI любого инсталляционного диска Windows). # Немного исправляет пути для стандартного шаблона Grub2 с Foreman, обеспечивающего chain-load:   # Забирает скрипты инсталляции Windows с Foreman:   # Добавляет скрипты в bootwim с помощью утилиты из комплекта wim-tools:   # Сообщает Foreman, что установка завершена, это позволит осуществить следующую загрузку с диска:   После выполнения этих процедур произойдет загрузка с WindowsPE с помощью штатного BCD Microsoft, расположенного на EFI-партиции. Дальнейшая процедура идентична установке с использованием прямой загрузки в WindowsPE — с той лишь разницей, что все необходимые скрипты установки загружены с Foreman, поэтому часть процедуры уже не нужна. Можно включить в startpe.cmd скрипт проверку на наличие этих файлов и перейти к исполнению основного скрипта инсталляции foreman.ps1 сразу, если он есть в системе. Разбивка диска также чуть усложняется для поддержки EFI. Вот вариант partition_table для Foreman (часть erb-шаблона, с конструкцией выбора efi/legacy): Поскольку WindowsPE уже загружен в память (речь конкретно о Boot.wim, в который мы добавляли установочные скрипты на этапе Linux), то диск можно полностью зачистить и создать чистую установку в соответствии с рекомендациями Microsoft по разбивке дисков для EFI-инсталляций. Дальнейшие шаги необходимо описать в foreman.ps1 — это PowerShell-скрипт, который произведет загрузку необходимых драйверов, образа wim (вместе с утилитой setup.exe) со штатного инсталляционного DVD Microsoft и запустит setup.exe с использованием файла ответов unattend.xml. Результат: установленная ОС Microsoft в режиме EFI с помощью сервиса Foreman и без использования инфраструктуры Microsoft.