Ускоренное импортозамещение или как разворачивать Linux-дистрибутив с помощью SCCM в распределённой корпоративной сети

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Когда нужно массово переустановить ОС на компьютерах в корпоративной сети, мы привыкли использовать System Center Configuration Manager (SCCM) и все хорошо, если речь идёт про Windows, но с Linux немного все сложнее, т.к. нет готовых инструментов в SCCM.

К счастью, SCCM удобный и гибкий инструмент, чтобы решить любую задачу по переустановке ОС. Если у вас инсталляция SCCM не распределённая, где все ПК находятся в одной сети, то вам подойдёт вот эта статья для установки ОС Linux с сетевой папки.

Если у вас распределённая инсталляция SCCM, где много Distribution Point в отдалённых локациях (с «небыстрыми» каналами связи), а установку нужно проводить на 100 ПК одновременно, то с сетевой папки сделать это сложно. Именно эту задачу нам понадобилось решить, попутно улучшив и автоматизировав способ, описанный выше (идея взята из упомянутой статьи и доработана, спасибо fisher51 и моим коллегам, кто помогал).

Итак, приступим.

Создаём виртуалку с минимальным диском, это важно, т.к. от размера будет зависеть размер итогового образа (для Xubuntu достаточно 9Gb). Устанавливаем Xubuntu (для примера), выбирая стандартное разделение дисков:

Разбивка диска
Разбивка диска

Как видно на скриншоте, у нас один диск 9Gb со стандартной разбивкой, где /dev/sda1 – загрузочная партиция (FAT32), /dev/sda2 – логический диск, /dev/sda5 – партиция самого Linux (ext4).

Далее настраиваете операционную систему, как вам нужно, например, в корпоративной среде можно сразу прописать настройки прокси (PAC файл), временную зону и т.д.

Образ можно снять либо на подключённый дополнительный диск, либо подключить сетевой. В последнем случае нам понадобится ещё она компонента:

apt install cifs-utils

Мы помним, что диск у нас уменьшен для минимизации размера образа, но после его разворачивания на обычных компьютерах, где диск более 9Gb, нам нужно его автоматически расширить без привлечения администратора. Также в виде автоматизации можно сделать ввод в домен при запуске системы, либо запуск любых других скриптов, но этот вопрос подробно рассматривать не буду, оставлю для специалистов.

Итак, делаем автоматизацию расширения диска при первом запуске системы.
Создаём/изменяем в директории /etc файл rc.local - это конфиг службы rc-local, которая будет запускаться при запуске системы и стартовать наш/и скрипт/ы.

sudo nano /etc/rc.local

Листинг rc.local

#!/bin/sh -e
exec /usr/sbin/res1.sh
exit 0

где: #!/bin/sh -e - запуск консоли, exec /usr/sbin/res1.sh – запуск скрипта res1.sh
Через команду exec сюда можно дописывать и другие скрипты, главное не забывать их отсюда удалять, иначе они будут запускаться при каждом запуске (хотя это тоже полезно, но не в моем случае).
Делаем этот файл исполняемым chmod +x /etc/rc.local
Создаём в директории /usr/sbin/ файл, называем, например, res1.sh

sudo nano /usr/sbin/res1.sh

Листинг res1.sh

echo -e "resizepart\n2\nYes\n100%\nresizepart\n5\nYes\n100%\nquit" | parted /dev/sda ---pretend-input-tty
echo 1 > /sys/block/sda/device/rescan
resize2fs /dev/sda5
sed -i '/res1.sh/d' /etc/rc.local
rm -f /usr/sbin/res1.sh
reboot

где:
1 строчка – передаём через конвейерный input команду для утилиты parted выполняем resizepart 2 на 100% диска и resizepart 5 на 100% , т.е. раздвигаем логическую и основную партицию linux до 100% диска
2 строчка – делает обновление информации о диске
3 строчка – расширяется файловая до конца диска
4 строчка – удаление строчки запуска скрипта из службы rc.local
5 строчка – удаление скрипта
res1.sh
6 строчка – перезагрузка

Делаем этот файл исполняемым: chmod +x /usr/sbin/res1.sh
Я буду снимать образ на сетевой диск, следовательно, подключим его:

mkdir /mnt/image
mount.cifs //имя_сервера/имя_сетевой_папки /mnt/image -o user=имя_пользователя,pass=пароль      

Теперь запустим снятие образа на добавленную сетевую папку.

dd if=/dev/sda of=/mnt/image/sda.dd.img bs=8M

где:
if- указываем с какого диска снимаем копию
of – указываем куда копируем образ
bs- размер блока чтения 8Мб

В итоге на сетевой папке у нас лежит образ sda.dd.img размером 9Gb, сжимаем его архиватором 7z, в Zip-файл sda.dd.zip (при выборе максимального сжатия у меня файл получился 2.14 Gb, при минимальном быстром сжатии 2.22 Gb что в целом очень хорошо).

Далее создаём сетевую папку, доступную по всей сети компании, с правами подключения под определённым аккаунтом. В папку выкладываем скрипт SetupLinux.ps1, который будет запускать в Task Sequence с определёнными параметрами.

[CmdletBinding()]
Param(
    [Parameter( Mandatory = $true, Position = 0 )]
    [ValidateSet( 'ShowProgressLinuxInstall', 'StartShowProgressLinuxInstall', 'CreatePartition', 'SetVariable', 'ShowProgressLinuxDownload', 'StartShowProgressLinuxDownload' )]
    [String]$Worktype
)

function Main ( $Worktype ) {
    switch ( $Worktype ) {
        'CreatePartition'   {
            $HardDisk = Get-Disk -Number 0
            $HardDiskSize = $HardDisk.Size
            if ($HardDiskSize -lt 20Gb) {
                Write-Host "Small disk, Exit" , $HardDiskSize
                Exit 1
            }
            Get-Disk -Number 0 | Where-Object PartitionStyle -EQ 'RAW' | Initialize-Disk
            Write-Host "Initialize Disk complete"
            #Start-Sleep -Seconds 5
            Get-Disk -Number 0 | Clear-Disk -RemoveData -RemoveOEM -Confirm:$false
            Write-Host "Clear Disk complete"
            #Start-Sleep -Seconds 5
            Get-Disk -Number 0 | Where-Object PartitionStyle -EQ 'RAW' | Initialize-Disk
            #Start-Sleep -Seconds 5
            Write-Host "Initialize Disk complete"
            $Offset = $HardDiskSize-5Gb-10Mb
            $NewPartition = Get-Disk -Number 0 | New-Partition -Size 5Gb -Offset $Offset -DriveLetter C
            #Start-Sleep -Seconds 5
            Write-Host "Create Partition complete"
            Format-Volume -FileSystem NTFS -Force -Partition $NewPartition
            #Start-Sleep -Seconds 5
            Write-Host "Format Partition Disk complete"
        }

        'StartShowProgressLinuxInstall' {
            Start-Process -WindowStyle Hidden -FilePath "powershell.exe" -ArgumentList "-WindowStyle Hidden -NoProfile -nologo -ExecutionPolicy Bypass -File T:\SetupLinux.ps1 -Worktype ShowProgressLinuxInstall"
            Exit
        }

        'ShowProgressLinuxInstall' {
            $TsProgressUI = New-Object -ComObject Microsoft.SMS.TsProgressUI
            $TotalProgressCount = (Get-Item C:\_SMSTaskSequence\Packages\MVI00424\sda.dd.zip).Length
            $CountAttempts = 10
            while ($CountAttempts -gt 0) {
                Start-Sleep -Seconds 5
                $CountAttempts = $CountAttempts - 1
                while (Get-WmiObject -Class win32_process -Filter {name = '7z.exe'}) {
                    $ProgressCount = (Get-WmiObject -Class win32_process -Filter {name = '7z.exe'}).ReadTransferCount
                    $Procent = $ProgressCount / $TotalProgressCount * 100
                    $TsProgressUI.ShowTSProgress("","","","Linux Install ($([math]::Round($Procent))% complete)",$Procent,100)
                    Start-Sleep -Seconds 5
                }
            }
        }

        'StartShowProgressLinuxDownload' {
            Start-Process -WindowStyle Hidden -FilePath "powershell.exe" -ArgumentList "-WindowStyle Hidden -NoProfile -nologo -ExecutionPolicy Bypass -File T:\SetupLinux.ps1 -Worktype ShowProgressLinuxDownload"
            Exit
        }
        
        'ShowProgressLinuxDownload' {
            $TsProgressUI = New-Object -ComObject Microsoft.SMS.TsProgressUI
            $CountAttempts = 10
            while ($CountAttempts -gt 0) {
                Start-Sleep -Seconds 5
                $CountAttempts = $CountAttempts - 1
                while (Get-WmiObject -Class win32_process -Filter {name = 'OSDDownloadContent.exe'}) {
                    $ProgressCount = (Get-WmiObject -Class win32_process -Filter {name = 'OSDDownloadContent.exe'}).ReadTransferCount
                    $TotalProgressCount = (Get-WmiObject -Class win32_process -Filter {name = 'OSDDownloadContent.exe'}).WriteTransferCount
                    if ($ProgressCount -gt 1048576) {
                        $Procent = $ProgressCount / $TotalProgressCount * 100
                        $TsProgressUI.ShowTSProgress("","","","Download Linux Package ($([math]::Round($Procent))% complete)",$Procent,100)
                    }
                    Start-Sleep -Seconds 5
                }
            }
        }

        'SetVariable' {
            Get-Disk -Number 0 | Update-Disk
            Get-Disk -Number 0 | Get-Partition | Where-Object -FilterScript {$_.Type -eq "FAT32"} | Set-Partition -NewDriveLetter C
            $TSEnvironment = New-Object -ComObject Microsoft.SMS.TSEnvironment
            $config = [PSCustomObject]@{
                OSDComputerName = $TSEnvironment.Value("OSDComputerName")
                IN_DOMAIN = $TSEnvironment.Value("IN_DOMAIN")
            }
            Out-File -FilePath C:\config.json -InputObject ($config | ConvertTo-Json) -Encoding utf8
        } 

    }

}
                                                                                                                                                                                                                                 
. Main $Worktype

Далее переходим в SCCM и создаём пакет.

Файлы пакета SCCM
Файлы пакета SCCM

В пакете у нас должны быть:
7z.dll , 7z.exe - программа 7z, чтобы распаковать архив (достаточно этих файлов)
ddrelease64.exe – утилита DD под Windows, берем отсюда, там есть 32- и 64-битная версия (я использую 64-битную, т.к. у меня boot образ x64)
sda.dd.zip – собственно сам файл архива.
install.cmd – пакетный файл установки.

Листинг install.cmd:

@echo off
cd C:_SMSTaskSequence\Packages\XXX00424
7z.exe e -so sda.dd.zip | ddrelease64.exe of=\?\Device\Harddisk0\Partition0 bs=8M

где:
XXX00424 – код текущего пакета, из которого производится запуск
с 3 строчкой поясню, распаковываем через 7z в консоль (параметр -so) файл sda.dd.zip далее передаём поток утилите ddrelease64.exe и сразу записываем его на диск \\?\Device\Harddisk0\Partition0 блоком 8Mb

Далее пакет распространяем на Distribution Point’ы.

Теперь создадим загрузочный Task Sequence

Выбираем Create a new custom task sequence, нажимаем далее.

Выбираем 64-битный загрузочный образ, нажимаем далее.

Добавляем шаг 1: перезагрузка, если при запуске задания введён неправильный пароль (защита от «дурака»)

Шаг 1-Properties
Шаг 1-Properties
Шаг 1 - Options
Шаг 1 - Options

Добавляем шаг 2: подключаем сетевую папку, доступную под определённым аккаунтом по всей сети, в которой лежит скрипт SetupLinux.ps1 (описанный выше).

Добавляем шаг 3: запуск PowerShell скрипта с параметром -WorkType CreatePartition для инициализации, очистки диска и создания временной NTFS партиции для загрузки образа.

Добавляем шаг 4: запуск PowerShell скрипта с параметром -WorkType StartShowProgressLinuxDownload для отображения прогресса скачки образа.

Добавляем шаг 5: скачивание пакета SCCM на созданный временный диск NTFS

Добавляем шаг 6: запуск PowerShell скрипта с параметром -WorkType StartShowProgressLinuxInstall для отображения прогресса установки образа.

Добавляем шаг 7: запуск командного файла install.cmd из скачанного на временный диск пакета SCCM.

Добавляем шаг 8: запуск PowerShell скрипта с параметром  -WorkType SetVariable, в этом шаге на диске, куда уже записали Linux, находим загрузочный диск с FAT32 для сохранения JSON файла с параметрами Task Sequence. Через него можно передать переменные имя компьютера OSDComputerName, нужно ли вводить ПК Linux в домен IN_DOMAIN, либо любые другие параметры. На эту партицию также можно положить любые скрипты, которые вы хотите запустить при запуске ОС Linux.

Далее добавляем Deployment для Task Sequence, указываем необходимые переменные.

Далее загружаемся по сети PXE и наслаждаемся установкой Linux из SCCM за 5-7 мин.

В итоге получилась заливка ОС Linux и партиция раздвинута до конца диска 40gb.

Чтобы убедится, что мы передали файл конфига из SCCM в Linux, подключим временно партицию /dev/sda1, командой  mount /dev/sda1 /mnt/cm

Параметры, переданные через JSON из Task Sequence

Вот и все, наслаждаемся работой Linux в корпоративной сети.

Удачи вам в ваших экспериментах.

Источник: https://habr.com/ru/company/mvideo/blog/670280/


Интересные статьи

Интересные статьи

Всем привет!Однажды меня попросили решить такую задачку в области транспортной логистики:Есть грузовые машины, которые изначально готовы стартовать в разное время из разных географических точек.Есть г...
Где только не применяют нейросети — от интернета вещей до распознавания текстов, в том числе древних рукописей. В этот раз машинное обучение помогло разобраться в свитках из Иудейской п...
Представим колл-центр. Сотрудник отвечает на входящий звонок: “Чем я могу Вам помочь?” И далее начинает взаимодействие с 40 различными приложениями на своем компьютере. В...
Помните как некто cnlohr запустил передачу ТВ сигнала на ESP8266? Недавно мне попалось к просмотру это видео, стало интересно как это возможно и выяснил что автор видео разогнал ча...
Рис. 1. – Внешний вид 4-х ступенчатого термоакустического двигателя с бегущей волной В предыдущих статьях я писал о том, как построить двигатель Стирлинга без поршней, то есть о том, как пос...