📜 ⬆️ ⬇️

Create a universal Install Server for an automatic network installation of Linux and Windows based on Cobbler

Cobbler is a tool in the Linux world that can be used as an Install Server, creating many installation scripts over a network based on one or more Linux distributions. There is also support for FreeBSD, VMware, Xen and Nexenta installations.

I would like to use it to also flexibly and universally create my own network installation scripts from various Windows distributions (XP, 2003, 7, 2008, 2012).

How to set up and use cobbler for installing Linux is exhaustively written on its official website - https://cobbler.imtqy.com . I will focus here on my version of solving the problem of Windows.

The main problem for creating your own network installation script was the preparation of the necessary Windows boot files for Linux. I generate the necessary binary files when I launch the cobbler post-trigger on the cobbler sync command:

In my case, the answer files are generated mainly based on the version of Windows and quite rarely, in addition, based on the profile name. Those. I chose for myself the most suitable and in most cases used installation options that can be specified in the answer file for each version of Windows.
')
The main work on setting up an installation option, installing additional software, etc. lies on the script, which I specify as a kickstart file for the cobbler profile (win.ks) in the case of Windows installation and downloaded by the script post_install.cmd already at the time of installation. Cobbler dynamically generates code at the moment of downloading based on the win.ks template. And in this template, most of the code is generated based on the profile name.

As a result, in most cases, in order to change the installation script when debugging, it is enough for me to simply edit the text file win.ks on the server and restart the installation.

By simplifying to the logical interrelationship of the files that need to be changed for each scenario, the network installation for Xp and 2003 can be schematically depicted like this:
pxeboot.n12 → setupldr.exe → winnt.sif → post_install.cmd profile_name


For Windos 7 and newer:
pxeboot.n12 → bootmgr.exe → BCD → winpe.wim → startnet.cmd → autounattended.xml → post_install.cmd profile_name


Not the shortest path from the point in the PXE menu to running the post_install.cmd script with the profile name as a parameter. In addition, this script should also take from the cobbler server kickstart corresponding to this profile and run it.

Now, first things first


We believe that cobbler 2.6.9 and everything you need to work with it is already installed, configured (for example, iptables, SElinux) and does an excellent job with installing Linux.

Install everything you need:

Using hivex is not directly convenient - here (a good installation option, but I didn’t like it because it uses tftp log analysis, but I don’t need to bounce binaries) I found a ready-made script (bcdedit.pl) that makes the necessary changes in the standard BCD . In fact, it is a replacement for the Windows utility bcdedit. It was written in Perl, I extracted it from the archive and put it in / usr / local / bin, having previously modified:
 # diff -c bcdedit.pl.orig bcdedit.pl *** bcdedit.pl.orig --- bcdedit.pl *************** *** 232,237 **** --- 232,238 ---- &AddElement($BCDFILE,$guids{bootmgr},"25000004","hex:3:1e,00,00,00,00,00,00,00"); &AddElement($BCDFILE,$guids{bootmgr},"12000004","string:Windows Boot Manager"); &AddElement($BCDFILE,$guids{bootmgr},"24000001",&Guids2MultiSZ($newguid)); + &AddElement($BCDFILE,$guids{bootmgr},"16000048","hex:3:01"); print "Creating New Object\n"; &CreateGuid($BCDFILE,$newguid,"0x10200003"); 

The added line is similar to the command:
 bcdedit -set {bootmgr} nointegritychecks Yes 

In the server's tftp directory, we create a folder where we will have the Windows distribution kits:
 # mkdir /var/lib/tftpboot/winos 

Now there we create directories for each distribution kit and we copy its contents there.
It looks like this to me:
 # ls -l /var/lib/tftpboot/winos dr-xr-xr-x. 6 root root 4096 Nov 29 2014 Win2012-Server_EN-x64 dr-xr-xr-x. 6 root root 4096 Jun 1 2014 Win2012-Server_RU-x64 dr-xr-xr-x. 10 root root 4096 May 6 19:41 Win2K3-Server_EN-x64 dr-xr-xr-x. 7 root root 4096 Nov 13 2013 Win2k8-Server_EN-x64 dr-xr-xr-x. 4 root root 4096 Oct 28 2013 Win7_EN-x64 dr-xr-xr-x. 5 root root 4096 Sep 25 2014 Win7_RU-x64 dr-xr-xr-x. 6 root root 4096 Jun 25 10:29 Win8_RU-x64 dr-xr-xr-x. 7 root root 4096 Dec 8 2011 WinXp_EN-i386 dr-xr-xr-x. 8 root root 4096 Jul 31 17:12 WinXp_RU-i386 

If you plan to install such rarities as Xp or 2003

Preparing boot files


In directories with WinXp_EN-i386, WinXp_RU-i386 and Win2K3-Server_EN-x64 distributions, we execute the following commands:
 [root@is WinXp_EN-i386]# cabextract i386/startrom.n1_ [root@is WinXp_EN-i386]# mv startrom.n12 pxeboot.n12 [root@is WinXp_EN-i386]# cabextract i386/setupldr.ex_ 

In the distribution directories with Xp:
 [root@is WinXp_EN-i386]# sed -i 's/ntdetect\.com/ntdetect.wxp/gi setupldr.exe 

In distribution directories since 2003:
 [root@is Win2K3-Server_EN-x64]# sed -i 's/ntdetect\.com/ntdetect.2k3/gi setupldr.exe 

 # cp /var/lib/tftpboot/winos/WinXp_EN-i386/i386/ntdetect.com /var/lib/tftpboot/winos/ntdetect.wxp # cp /var/lib/tftpboot/winos/Win2K3-Server_EN-x64/i386/ntdetect.com /var/lib/tftpboot/winos/ntdetect.wxp 

RIS setup


We need ris-linux. In my distribution, it is set as follows:
 # dnf install ris-linux 

In order for RIS not to interfere with the installation of Win 7, you need to comment on one line in the /usr/share/ris-linux/binlsrv.py file:
 # cd /usr/share/ris-linux # cp binlsrv.py binlsrv.py.orig # sed -i "s/p = p + chr(252) + chr(len(/#&/gi" binlsrv.py 

 # diff binlsrv.py.orig binlsrv.py 571c571 < p = p + chr(252) + chr(len('boot\\bcd')) + 'boot\\bcd' --- > #p = p + chr(252) + chr(len('boot\\bcd')) + 'boot\\bcd' 

I did not manage to find a simple way, without analyzing the tftpd logs, the ability to specify which BIS RIS is needed. So just turned it off.

Create a folder / var / lib / tftpboot / winos / inf and copy there all the .inf files of 32-bit network card drivers that you need and run the command:
 # /usr/share/ris-linux/infparser.py /var/lib/tftpboot/winos/inf 

I need RIS to simultaneously serve 32-bit Xp and 64-bit Server 2003. To do this, create another instance of the service on another port:
 # cd /etc/sysconfig # cp ris-linuxd ris-linuxd64 # sed -i 's/\/inf/&64/gi' ris-linuxd64 # sed -i 's/linuxd/&64/gi' ris-linuxd64 # sed -i 's/BINLSRV_OPTS=/&--port=4012/gi' ris-linuxd64 

 # diff ris-linuxd ris-linuxd64 2c2 < # ris-linuxd service. --- > # ris-linuxd64 service. 6c6 < BINLSRV_INFPATH=/var/lib/tftpboot/winos/inf --- > BINLSRV_INFPATH=/var/lib/tftpboot/winos/inf64 9c9 < BINLSRV_OPTS= --- > BINLSRV_OPTS=--port=4012 12c12 < BINLSRV_LOGFILE=/var/log/ris-linuxd.log --- > BINLSRV_LOGFILE=/var/log/ris-linuxd64.log 15c15 < BINLSRV_PIDFILE=/var/run/ris-linuxd.pid --- > BINLSRV_PIDFILE=/var/run/ris-linuxd64.pid 

 # cd /usr/sbin # ln -s ris-linuxd ris-linuxd64 

Nobody bothered to rewrite the ris-linux service under systemd, however nobody needs it anymore.
 # cd /etc/rc.d/init.d # cp ris-linuxd ris-linuxd64 # sed -i 's/ris-linuxd/&64/gi' ris-linuxd64 

Create the folder / var / lib / tftpboot / winos / inf64 and copy there all the .inf files of 64-bit network card drivers that you need and run the command:
 /usr/share/ris-linux/infparser.py /var/lib/tftpboot/winos/inf64 

We include and start services:
 # systemctl enable ris-linuxd # systemctl start ris-linuxd # systemctl enable ris-linuxd64 # systemctl start ris-linuxd64 

Additionally, you need to change the port in the Win2K3-Server_EN-x64 bootloader to the one that we specified to 64-bit RIS.
This can be done using the modldr.py utility from the ris-linux package:
 # /usr/share/ris-linux/modldr.py -p 4012 /var/lib/tftpboot/winos/Win2K3-Server_EN-x64/setupldr.exe 

If the work of the utility ends in an error, then in the text of the modldr.py script, replace the line:
 ppattern = re.compile(r'\x6a\x04\x68(..)\x00\x00\xff\x35', re.DOTALL) 

per line:
 ppattern = re.compile(r'\x6a\x64\x68(..)\x00\x00\xff\x35', re.DOTALL) 


SAMBA preparation


We need Samba to make two folders public.
 # vi /etc/samba/smb.conf #    [WINOS] path = /var/lib/tftpboot/winos guest ok = yes browseable = yes writeable = no public = yes blocking locks = no oplocks = no level2 oplocks = no #     [public] comment = Public Stuff path = /var/www/html/Distr public = yes writable = no printable = no guest ok = yes blocking locks = no oplocks = no level2 oplocks = no 


Create a user with minimal rights, which will be used during the installation. I have: install / install

Preparing files for a network installation Win 7, 8, 2008, 2012


The situation with Win 7, 8, 2008, 2012 is much worse than in Xp. It's not so easy to dig into binaries here - then you need to recalculate the checksum in it.

The answer file for automatic installation is also available here in a more modern form - in the xml format. There are a lot of improvements in it, for example, you can specify how to cut disks into partitions, etc. But there is also a big spoon of tar - the name of the answer file is sewn into the start script, which actually starts the installation. In turn, the script itself is sewn into a wim image.

Those. There are still more inconveniences with fixing binaries, and besides for each installation scenario based on one distribution I now have to have a separate wim image that differs from the other same image only by the name of the answer file in the start script.

The following files should be put in the distribution directories:

Creating Cobbler Templates


Create rules for converting file names to tftp:
The contents of the file /etc/tftpd.rules
 #vi /etc/tftpd.rules rg \\ / # Convert backslashes to slashes r (BOOTFONT\.BIN) /winos/\1 r (/Boot/Fonts/)(.*) /winos/Win8_RU-x64/boot/Fonts/\2 r (ntdetect\.wxp) /winos/\1 r (ntdetect\.2k3) /winos/\1 r (wine.\.sif) /WinXp_EN-i386/\1 r (xple.) /WinXp_EN-i386/\1 r (winr.\.sif) /WinXp_RU-i386/\1 r (xplr.) /WinXp_RU-i386/\1 r (wi2k.\.sif) /Win2K3-Server_EN-x64/\1 r (w2k3.) /Win2K3-Server_EN-x64/\1 r (/Win2K3-Server_EN-x64/)(.*) /winos\1\L\2 r (boot7r..exe) /winos/Win7_RU-x64/\1 r (/Boot/)(7R.) /winos/Win7_RU-x64/boot/\2 r (boot7e.\.exe) /winos/Win7_EN-x64/\1 r (/Boot/)(7E.) /winos/Win7_EN-x64/boot/\2 r (boot28.\.exe) /winos/Win2k8-Server_EN-x64/\1 r (/Boot/)(28.) /winos/Win2k8-Server_EN-x64/boot/\2 r (boot2e.\.exe) /winos/Win2012-Server_EN-x64/\1 r (/Boot/)(2e.) /winos/Win2012-Server_EN-x64/boot/\2 r (boot2r.\.exe) /winos/Win2012-Server_RU-x64/\1 r (/Boot/)(2r.) /winos/Win2012-Server_RU-x64/boot/\2 r (boot81.\.exe) /winos/Win8_RU-x64/\1 r (/Boot/)(B8.) /winos/Win8_RU-x64/boot/\2 r (/WinXp...-i386/)(.*) /winos\1\L\2 


Specify the conversion rules in the tftp cobbler template:
 # vi /etc/cobbler/tftpd.template service tftp { disable = no socket_type = dgram protocol = udp wait = yes user = $user server = $binary server_args = -m /etc/tftpd.rules --port-range 25000:25030 -v -v -v -s $args per_source = 11 cps = 100 2 flags = IPv4 } 

We add version information in the /var/lib/cobbler/distro_signatures.json file to the windows section so that they can be used in cobbler metadata in templates.
 # vi /var/lib/cobbler/distro_signatures.json "windows": { "2003": { }, "2008": { }, "2012": { }, "XP": { }, "7": { }, "8": { } }, 

When setting up a Windows installation, it was possible to retain the main advantages of a Linux installation through cobbler by creating an answer file and a post-installation script from templates.

I have the following files in my Windows templates:
  1. post_inst_cmd.template - script template to be launched after OS installation
  2. win.ks - plays the role of the post section in kiskstart linux for windows
  3. win_sif.template - response file template
  4. startnet.template - start script template in wim image
  5. winpe7.template - wim file for Win 7 and Win 2008 Server
  6. winpe8.template - wim file for Win 8 and Win 2012 Server

Templates post_inst_cmd.template and win.ks


Create a script template that runs after installing windows (no matter which version).
The name of the profile (installation option) cobbler as a parameter is passed to the script upon startup.
 # cat /var/lib/tftpboot/winos/post_inst_cmd.template %systemdrive% CD %systemdrive%\TMP >nul 2>&1 $SNIPPET('my/win_wait_network_online') wget.exe http://@@http_server@@/cblr/svc/op/ks/profile/%1 MOVE %1 install.cmd todos.exe install.cmd start /wait install.cmd DEL /F /Q libeay32.dll >nul 2>&1 DEL /F /Q libiconv2.dll >nul 2>&1 DEL /F /Q libintl3.dll >nul 2>&1 DEL /F /Q libssl32.dll >nul 2>&1 DEL /F /Q wget.exe >nul 2>&1 DEL /F /Q %0 >nul 2>&1 

A few explanations of the pattern:
In each directory with the distribution there is a folder $ OEM $ / $ 1 / TMP which contains wget.exe, todos.exe and dll'ki necessary for them to run. More precisely, they are in the same folder, while others just symlink to it.
 # ls -l '/var/lib/tftpboot/winos/Win2K3-Server_EN-x64/$OEM$/$1/TMP' -rwxr-xr-x. 1 root root 1177600 Sep 4 2008 libeay32.dll -rwxr-xr-x. 1 root root 1008128 Mar 15 2008 libiconv2.dll -rwxr-xr-x. 1 root root 103424 May 7 2005 libintl3.dll -rwxr-xr-x. 1 root root 232960 Sep 4 2008 libssl32.dll -rwxr-xr-x. 1 root root 4880 Oct 26 1999 sleep.exe -rwxr-xr-x. 1 root root 52736 Oct 27 2013 todos.exe -rwxr-xr-x. 1 root root 449024 Dec 31 2008 wget.exe # ls -l '/var/lib/tftpboot/winos/Win8_RU-x64/sources/$OEM$/$1/TMP' lrwxrwxrwx. 1 root root 45 Oct 28 2013 /var/lib/tftpboot/winos/Win8_RU-x64/sources/$OEM$/$1/TMP -> ../../../../Win2K3-Server_EN-x64/$OEM$/$1/TMP # ls -l '/var/lib/tftpboot/winos/WinXp_RU-i386/$OEM$/$1/TMP' lrwxrwxrwx. 1 root root 42 May 31 2014 /var/lib/tftpboot/winos/WinXp_RU-i386/$OEM$/$1/TMP -> ../../../Win2K3-Server_EN-x64/$OEM$/$1/TMP 


The file that we downloaded by wget and which plays the role of the post-installation part of the Linux kickstart looks like in a simplified form:
Contents of the /var/lib/cobbler/kickstarts/win.ks file
 # cat /var/lib/cobbler/kickstarts/win.ks $SNIPPET('my/win_wait_network_online') set n=0 :mount_y net use y: \\@@http_server@@\Public /user:install install set exit_code=%ERRORLEVEL% IF %exit_code% EQU 0 GOTO mount_z set /an=n+1 IF %n% lss 20 goto mount_y PAUSE goto mount_y set n=0 :mount_z net use z: \\@@http_server@@\winos /user:install install set exit_code=%ERRORLEVEL% IF %exit_code% EQU 0 GOTO mount_exit set /an=n+1 IF %n% lss 20 goto mount_z PAUSE goto mount_z :mount_exit if exist %systemdrive%\TMP\stage.dat goto flag005 echo 0 > %systemdrive%\TMP\stage.dat $SNIPPET('my/win_check_virt') #if $distro_name in ( 'WinXp_EN-i386', 'WinXp_RU-i386', 'Win2K3-Server_EN-x64' ) z:\Drivers\wsname.exe /N:$DNS /NOREBOOT #else REM pause #end if echo Windows Registry Editor Version 5.00 > %systemdrive%\TMP\install.reg echo [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce] >> %systemdrive%\TMP\install.reg echo "DD"="C:\\TMP\\install.cmd" >> %systemdrive%\TMP\install.reg $SNIPPET('my/win_install_drivers') #if $distro_name == 'Win2K3-Server_EN-x64' start /wait z:\Win2K3-Server_EN-x64\cmpnents\r2\setup2.exe /q /a /sr start /wait y:\Windows\Win2003\IE8-WindowsServer2003-x64-ENU.exe /passive /update-no /norestart if %virt% equ NO REG IMPORT y:\Windows\Win2003\vm.reg #end if REG IMPORT %systemdrive%\TMP\install.reg net use Y: /delete net use Z: /delete %systemdrive%\TMP\sleep.exe 10 exit :flag005 for /f "tokens=*" %%i in (%systemdrive%\TMP\stage.dat) do set stage=%%i echo 1 > %systemdrive%\TMP\stage.dat REG IMPORT %systemdrive%\TMP\install.reg if %stage% neq 0 goto flag010 net use Y: /delete net use Z: /delete shutdown -r -f -t 5 exit :flag010 if %stage% gtr 1 goto flag020 echo 2 > %systemdrive%\TMP\stage.dat $SNIPPET('my/winzip') $SNIPPET('my/winrar') $SNIPPET('my/win_install_chrome') $SNIPPET('my/win_install_ffox') $SNIPPET('my/win_install_adacr') $SNIPPET('my/win_install_jdk7-x86') $SNIPPET('my/win_install_jdk7-x86_64') $SNIPPET('my/win_install_UltraVNC') #if $distro_name in ( 'WinXp_EN-i386', 'WinXp_RU-i386', 'Win2K3-Server_EN-x64' ) $SNIPPET('my/win_install_office_2007_ru') #else if $distro_name in ( 'Win7_RU-x64', 'Win2012-Server_RU-x64', 'Win8_RU-x64' ) $SNIPPET('my/win_install_office_2010_ru') #else $SNIPPET('my/win_install_office_2010_en') #end if Title Cleaning Temp files DEL "%systemroot%\*.bmp" >nul 2>&1 DEL "%systemroot%\Web\Wallpaper\*.jpg" >nul 2>&1 DEL "%systemroot%\system32\dllcache\*.scr" >nul 2>&1 DEL "%systemroot%\system32\*.scr" >nul 2>&1 DEL "%AllUsersProfile%\Start Menu\Windows Update.lnk" >nul 2>&1 DEL "%AllUsersProfile%\Start Menu\Set Program Access and Defaults.lnk" >nul 2>&1 DEL "%AllUsersProfile%\Start Menu\Windows Catalog.lnk" >nul 2>&1 DEL "%systemdrive%\Microsoft Office*.txt" >nul 2>&1 net user aspnet /delete >nul 2>&1 REM %systemdrive%\TMP\sleep.exe 60 net use Y: /delete net use Z: /delete shutdown -r -f -t 30 RD /S /Q %systemdrive%\DRIVERS\ >nul 2>&1 if not defined stage DEL /F /Q %systemdrive%\post_install.cmd DEL /F /S /Q %systemdrive%\TMP\*.* exit 


Snippets here are used in order not to clutter up the code. They carry out checks on the hypervisor, install the necessary drivers, depending on the distribution kit and the profile, this or that software is installed or not.

Template win_sif.template


This is a single template from which answer files of all windows versions are formed. In it, as in other templates, you can use all the cobbler meta-variables.
Such as $ arch, $ distro_name, $ profile_name.
Contents of the /var/lib/tftpboot/winos/win_sif.template file
 #if $distro_name in ( 'WinXp_EN-i386', 'WinXp_RU-i386', 'Win2K3-Server_EN-x64' ) #if $arch == 'x86_64' #set $win_arch = 'amd64' #else if $arch == 'i386' #set $win_arch = 'i386' #end if #set $OriSrc = '\\\\' + $http_server + '\\WINOS\\' + $distro_name + '\\' + $win_arch #set $DevSrc = '\\Device\\LanmanRedirector\\' + $http_server + '\\WINOS\\' + $distro_name [Data] floppyless = "1" msdosinitiated = "1" ; Needed for second stage OriSrc="$OriSrc" OriTyp="4" LocalSourceOnCD=1 DisableAdminAccountOnDomainJoin=0 AutomaticUpdates="No" Autopartition="0" UnattendedInstall="Yes" [SetupData] OsLoadOptions = "/noguiboot /fastdetect" ; Needed for first stage SetupSourceDevice = "$DevSrc" [Unattended] CrashDumpSetting=0 FactoryMode=No UnattendMode=FullUnattended UnattendSwitch="Yes" OemPreinstall="Yes" OemSkipEula="Yes" Repartition=No FileSystem=* WaitForReboot="No" NoWaitAfterTextMode=1 NoWaitAfterGUIMode=1 DriverSigningPolicy=Ignore NonDriverSigningPolicy=Ignore UpdateInstalledDrivers=Yes TargetPath=\WINDOWS OemPnPDriversPath=DRIVERS\NIC;DRIVERS\ACPI;DRIVERS\CHIPSET\5520\All;DRIVERS\CHIPSET\C200\All;DRIVERS\Storage;DRIVERS\Virt #if $os_version == '2003' [LicenseFilePrintData] AutoMode = PerSeat #end if [Display] BitsPerPel=32 XResolution=1440 YResolution=900 Vrefresh=60 [WindowsFirewall] Profiles = WindowsFirewall.TurnOffFirewall [WindowsFirewall.TurnOffFirewall] Mode = 0 [PCHealth] RA_AllowToGetHelp=0 [GuiRunOnce] "%Systemdrive%\post_install.cmd @@profile_name@@" [GuiUnattended] AdminPassword=* TimeZone=195 OEMSkipRegional=1 OemSkipWelcome=1 #if $os_version != '2003' AutoLogon = Yes AutoLogonCount=1 #end if [RemoteInstall] Repartition=Yes UseWholeDisk=Yes [Components] msmsgs=Off msnexplr=Off zonegames=Off Paint=Off #if $os_version == '2003' ; Iis_common=On ; Iis_inetmgr=On ComPlusNetwork=On ; Iis_www=On ; Iis_asp=On IEHardenAdmin=Off IEHardenUser=Off #end if [TerminalServices] AllowConnections=1 [UserData] #if $os_version == '2003' ProductKey="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX" #else if $distro_name == 'WinXp_EN-i386' ProductKey="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX" #else if $distro_name == 'WinXp_RU-i386' ProductKey="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX" #end if ComputerName=* FullName="Admin" OrgName="Microsoft" [RegionalSettings] LanguageGroup=1,2,3,4,5 #if $distro_name == 'WinXp_RU-i386' SystemLocale=00000419 UserLocale=00000419 #else SystemLocale=00000409 UserLocale=00000409 #end if InputLocale=0409:00000409,0419:00000419 [Shell] CustomDefaultThemeFile="%WinDir%\Resources\Themes\Windows Classic.Theme" [Networking] InstallDefaultComponents="Yes" 

 #else if $distro_name in ( 'Win7_RU-x64', 'Win7_EN-x64', 'Win2k8-Server_EN-x64', 'Win2012-Server_EN-x64', 'Win2012-Server_RU-x64', 'Win8_RU-x64' ) <?xml version="1.0" encoding="utf-8"?> <unattend xmlns="urn:schemas-microsoft-com:unattend"> #if $distro_name in ( 'Win2012-Server_EN-x64', 'Win2012-Server_RU-x64' ) <servicing> <package action="configure"> <assemblyIdentity name="Microsoft-Windows-ServerCore-Package" version="6.3.9600.16384" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="" /> <selection name="IIS-WebServerRole" state="true" /> <selection name="Microsoft-Hyper-V" state="true" /> <selection name="Microsoft-Hyper-V-Offline" state="true" /> <selection name="Microsoft-Hyper-V-Online" state="true" /> <selection name="Microsoft-Hyper-V-Management-Clients" state="true" /> <selection name="Microsoft-Hyper-V-Management-PowerShell" state="true" /> <selection name="VmHostAgent" state="true" /> <selection name="FailoverCluster-FullServer" state="true" /> <selection name="FailoverCluster-PowerShell" state="true" /> <selection name="FailoverCluster-CmdInterface" state="true" /> <selection name="MultipathIo" state="true" /> <selection name="ServerManager-Core-RSAT-Role-Tools" state="true" /> <selection name="RSAT-Hyper-V-Tools-Feature" state="true" /> <selection name="ServerManager-Core-RSAT" state="true" /> <selection name="ServerMediaFoundation" state="true" /> <selection name="Remote-Desktop-Services" state="true" /> <selection name="IIS-WebServer" state="true" /> <selection name="IIS-ApplicationDevelopment" state="true" /> <selection name="IIS-CommonHttpFeatures" state="true" /> <selection name="IIS-HealthAndDiagnostics" state="true" /> <selection name="IIS-Performance" state="true" /> <selection name="IIS-Security" state="true" /> <selection name="IIS-WebServerManagementTools" state="true" /> </package> </servicing> #end if <settings pass="windowsPE"> <component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> #if $distro_name in ( 'Win7_RU-x64', 'Win2012-Server_RU-x64', 'Win8_RU-x64' ) <InputLocale>0409:00000409;0419:00000419</InputLocale> <SystemLocale>ru-RU</SystemLocale> <UILanguage>ru-RU</UILanguage> <UILanguageFallback>ru-RU</UILanguageFallback> <UserLocale>ru-RU</UserLocale> #else <InputLocale>0409:00000409</InputLocale> <SystemLocale>en-US</SystemLocale> <UILanguage>en-US</UILanguage> <UILanguageFallback>en-US</UILanguageFallback> <UserLocale>en-US</UserLocale> #end if </component> <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <DiskConfiguration> <WillShowUI>OnError</WillShowUI> <Disk wcm:action="add"> <CreatePartitions> <CreatePartition wcm:action="add"> <Order>1</Order> <Extend>true</Extend> <Type>Primary</Type> </CreatePartition> </CreatePartitions> <DiskID>0</DiskID> <WillWipeDisk>true</WillWipeDisk> </Disk> </DiskConfiguration> <ImageInstall> <OSImage> <InstallFrom> <Credentials> <Domain></Domain> </Credentials> <MetaData wcm:action="add"> <Key>/IMAGE/NAME</Key> #if $profile_name == 'IOS' <Value>Windows8_VmVare_MacOS_xCode</Value> #else if $distro_name in ( 'Win7_RU-x64', 'Win7_EN-x64' ) <Value>Windows 7 PROFESSIONAL</Value> #else if $distro_name in ( 'Win2k8-Server_EN-x64' ) <Value>Windows Server 2008 R2 SERVERENTERPRISE</Value> #else if $distro_name in ( 'Win2012-Server_EN-x64', 'Win2012-Server_RU-x64' ) <Value>Windows Server 2012 R2 SERVERDATACENTER</Value> #else if $distro_name in ( 'Win8_RU-x64' ) <Value>Windows 8.1 Pro</Value> #else if $distro_name in ( 'Win8_EN-x64' ) <Value>Windows 8.1 Enterprise</Value> #end if </MetaData> </InstallFrom> <InstallTo> <DiskID>0</DiskID> <PartitionID>1</PartitionID> </InstallTo> </OSImage> </ImageInstall> <UserData> <ProductKey> #if $distro_name in ( 'Win2012-Server_EN-x64', 'Win2012-Server_RU-x64' ) <Key>XXXXX-XXXXX-XXXXX-XXXXX-XXXXX</Key> #end if <WillShowUI>Never</WillShowUI> </ProductKey> <AcceptEula>true</AcceptEula> <FullName>User</FullName> <Organization>My Organization</Organization> </UserData> <EnableFirewall>false</EnableFirewall> </component> <component name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <DriverPaths> #if $distro_name in ( 'Win2012-Server_EN-x64', 'Win2012-Server_RU-x64', 'Win8_RU-x64' ) <PathAndCredentials wcm:action="add" wcm:keyValue="1"> <Path>\\@@http_server@@\WINOS\Drivers\CHIPSET\Win8</Path> </PathAndCredentials> #else <PathAndCredentials wcm:action="add" wcm:keyValue="1"> <Path>\\@@http_server@@\WINOS\Drivers\CHIPSET\5520\Vista</Path> </PathAndCredentials> <PathAndCredentials wcm:action="add" wcm:keyValue="2"> <Path>\\@@http_server@@\WINOS\Drivers\CHIPSET\C200\WIN7</Path> </PathAndCredentials> #end if <PathAndCredentials wcm:action="add" wcm:keyValue="3"> #if $distro_name in ( 'Win2012-Server_EN-x64', 'Win2012-Server_RU-x64', 'Win8_RU-x64' ) <Path>\\@@http_server@@\WINOS\Drivers\NIC\Win8</Path> #else <Path>\\@@http_server@@\WINOS\Drivers\NIC</Path> #end if </PathAndCredentials> #if $distro_name in ( 'Win7_RU-x64', 'Win7_EN-x64', 'Win2k8-Server_EN-x64' ) <PathAndCredentials wcm:action="add" wcm:keyValue="4"> <Path>\\@@http_server@@\WINOS\Drivers\ACPI\64\WIN7</Path> </PathAndCredentials> #end if <PathAndCredentials wcm:action="add" wcm:keyValue="5"> <Path>\\@@http_server@@\WINOS\Drivers\Storage\64</Path> </PathAndCredentials> <PathAndCredentials wcm:action="add" wcm:keyValue="6"> #if $distro_name in ( 'Win8_RU-x64' ) <Path>\\@@http_server@@\WINOS\Drivers\Virt\Win8</Path> #else if $distro_name in ( 'Win2012-Server_EN-x64', 'Win2012-Server_RU-x64' ) <Path>\\@@http_server@@\WINOS\Drivers\Virt\2012</Path> #else if $distro_name in ( 'Win2k8-Server_EN-x64' ) <Path>\\@@http_server@@\WINOS\Drivers\Virt\2008</Path> #else <Path>\\@@http_server@@\WINOS\Drivers\Virt\Win7</Path> #end if </PathAndCredentials> </DriverPaths> </component> </settings> <settings pass="offlineServicing"> <component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <EnableLUA>false</EnableLUA> </component> </settings> <settings pass="specialize"> <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ComputerName>*</ComputerName> <RegisteredOrganization>My Organization</RegisteredOrganization> <RegisteredOwner>Instructor</RegisteredOwner> #if $distro_name == 'Win7_RU-x64' <ProductKey>XXXXX-XXXXX-XXXXX-XXXXX-XXXXX</ProductKey> #else if $distro_name == 'Win7_EN-x64' <ProductKey>XXXXX-XXXXX-XXXXX-XXXXX-XXXXX</ProductKey> #else if $distro_name == 'Win2k8-Server_EN-x64' <ProductKey>XXXXX-XXXXX-XXXXX-XXXXX-XXXXX</ProductKey> #else if $distro_name in ( 'Win2012-Server_EN-x64', 'Win2012-Server_RU-x64' ) <ProductKey>XXXXX-XXXXX-XXXXX-XXXXX-XXXXX</ProductKey> #end if </component> <component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Identification> <JoinWorkgroup>WORKGROUP</JoinWorkgroup> </Identification> </component> <component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <fDenyTSConnections>false</fDenyTSConnections> </component> <component name="Networking-MPSSVC-Svc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <FirewallGroups> <FirewallGroup wcm:action="add" wcm:keyValue="EnableRemoteDesktop"> <Active>true</Active> <Group>Remote Desktop</Group> <Profile>all</Profile> </FirewallGroup> </FirewallGroups> </component> <component name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <UserAuthentication>0</UserAuthentication> </component> </settings> <settings pass="oobeSystem"> <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <OOBE> <ProtectYourPC>3</ProtectYourPC> <NetworkLocation>Work</NetworkLocation> </OOBE> <UserAccounts> <AdministratorPassword> <Value>XXXX</Value> <PlainText>false</PlainText> </AdministratorPassword> <LocalAccounts> <LocalAccount wcm:action="add"> <Password> <Value>XXXXX</Value> <PlainText>false</PlainText> </Password> <Name>User</Name> <Group>Administrators</Group> </LocalAccount> </LocalAccounts> <DomainAccounts> <DomainAccountList wcm:action="add"> <Domain>WORKGOUP</Domain> <DomainAccount wcm:action="add"> <Name>Domain Admins</Name> <Group>Administrators</Group> </DomainAccount> <DomainAccount wcm:action="add"> <Name>User</Name> <Group>Administrators</Group> </DomainAccount> </DomainAccountList> </DomainAccounts> </UserAccounts> <TimeZone>Central Asia Standard Time</TimeZone> <RegisteredOrganization>My Organization</RegisteredOrganization> <RegisteredOwner>User</RegisteredOwner> <FirstLogonCommands> <SynchronousCommand wcm:action="add"> <RequiresUserInput>false</RequiresUserInput> <Order>1</Order> <CommandLine>cmd /C wmic useraccount where "name='user'" set PasswordExpires=FALSE</CommandLine> </SynchronousCommand> <SynchronousCommand wcm:action="add"> <RequiresUserInput>false</RequiresUserInput> <Order>2</Order> <CommandLine>c:\post_install.cmd @@profile_name@@</CommandLine> </SynchronousCommand> </FirstLogonCommands> <AutoLogon> <Password> <Value>XXXX</Value> <PlainText>false</PlainText> </Password> <Enabled>true</Enabled> <Domain>WORKGOUP</Domain> <Username>User</Username> <LogonCount>10000</LogonCount> </AutoLogon> </component> </settings> #if $distro_name in ( 'Win7_RU-x64', 'Win7_EN-x64' ) <cpi:offlineImage cpi:source="catalog:d:/sources/install_windows 7 professional.clg" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> #else if $distro_name in ( 'Win2k8-Server_EN-x64' ) <cpi:offlineImage cpi:source="catalog:d:/sources/install_windows server 2008 r2 serverenterprise.clg" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> #else if $distro_name in ( 'Win2012-Server_EN-x64', 'Win2012-Server_RU-x64' ) <cpi:offlineImage cpi:source="wim:c:/netboot/install.wim#Windows Server 2012 R2 SERVERDATACENTER" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> #else if $distro_name in ( 'Win8_RU-x64' ) <cpi:offlineImage cpi:source="catalog:d:/sources/install_windows 8.1 Pro.clg" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> #end if </unattend> #end if 


, :

startnet.template


wim .

/var/lib/cobbler/kickstarts/startnet.template
 wpeinit ping 127.0.0.1 -n 10 >nul md \tmp cd \tmp ipconfig /all | find "DHCP Server" > dhcp ipconfig /all | find "IPv4 Address" > ipaddr FOR /F "eol=- tokens=2 delims=:" %%i in (dhcp) do set dhcp=%%i FOR %%i in (%dhcp%) do set dhcp=%%i FOR /F "eol=- tokens=2 delims=:(" %%i in (ipaddr) do set ipaddr=%%i net use y: \\%dhcp%\Public /user:install install net use z: \\%dhcp%\WINOS\@@distro_name@@ /user:install install set exit_code=%ERRORLEVEL% IF %exit_code% EQU 0 GOTO GETNAME echo "Can't mount network drive goto EXIT :GETNAME y:\windows\bind\nslookup.exe %ipaddr% | find "name =" > wsname for /f "eol=- tokens=2 delims==" %%i in (wsname) do echo %%i > ws for /f "eol=- tokens=1 delims=." %%i in (ws) do set wsname=%%i FOR %%i in (%wsname%) do set wsname=%%i #set $unattended = "set UNATTENDED_ORIG=Z:\\sources\\" + $kernel_options["sif"] $unattended set UNATTENDED=X:\tmp\autounattended.xml echo off FOR /F "tokens=1 delims=!" %%l in (%UNATTENDED_ORIG%) do ( IF "%%l"==" <ComputerName>*</ComputerName>" ( echo ^<ComputerName^>%wsname%^<^/ComputerName^>>> %UNATTENDED% ) else ( echo %%l>> %UNATTENDED% ) ) echo on :INSTALL set n=0 z:\sources\setup.exe /unattend:%UNATTENDED% set /an=n+1 ping 127.0.0.1 -n 5 >nul IF %n% lss 20 goto INSTALL :EXIT 


winpe7.template winpe8.template


Win 7 Win 8 .
cobbler sync .
, startnet.template post-sync.

wim Linux wimlib
ntfs-3g, fuse.
, cobbler linux lxc libvirt, xml :
  <hostdev mode='capabilities' type='misc'> <source> <char>/dev/fuse</char> </source> </hostdev> 


cobbler:
 # systemctl restart cobblerd # cobbler distro add --name=WinXp_RU-i386 --kernel=/var/lib/tftpboot/winos/WinXp_RU-i386/pxeboot.n12 --initrd=/var/lib/tftpboot/winos/add_ram.dat --arch=i386 --breed=windows --os-version=XP --kopts='post_install=/var/lib/tftpboot/winos/WinXp_RU-i386/$OEM$/$1/post_install.cmd' # cobbler distro add --name=Win7_RU-x64 --kernel=/var/lib/tftpboot/winos/Win7_RU-x64/pxeboot.n12 --initrd=/var/lib/tftpboot/winos/add_ram.dat --arch=x86_64 --breed=windows --os-version=7 --kopts='post_install=/var/lib/tftpboot/winos/Win7_RU-x64/sources/$OEM$/$1/post_install.cmd' # cobbler distro add --name=Win8_RU-x64 --kernel=/var/lib/tftpboot/winos/Win8_RU-x64/pxeboot.n12 --initrd=/var/lib/tftpboot/winos/add_ram.dat --arch=x86_64 --breed=windows --os-version=8 --kopts='post_install=/var/lib/tftpboot/winos/Win8_RU-x64/sources/$OEM$/$1/post_install.cmd'  .. 

kernel — PXE pxeboot.n12 cobbler sync .
/var/lib/tftpboot/winos/add_ram.dat initrd, — distro .

cobbler:
 # cobbler profile add --name=WinXp_RU-i386 --distro=WinXp_RU-i386 --kickstart=/var/lib/cobbler/kickstarts/win.ks --kopts='pxeboot=winr0.0,bootmgr=xplr0,sif=winr0.sif' # cobbler profile add --name=Win7_RU-x64 --distro=Win7_RU-x64 --kickstart=/var/lib/cobbler/kickstarts/win.ks --kopts='pxeboot=win7ra.0,bootmgr=boot7ra.exe,bcd=7Ra,winpe=winpe.wim,sif=autounattended.xml' # cobbler profile add --name=Win8_RU-x64 --distro=Win8_RU-x64 --kickstart=/var/lib/cobbler/kickstarts/win.ks --kopts='pxeboot=win81a.0,bootmgr=boot81a.exe,bcd=B8a,winpe=winpe.wim,sif=autounattended.xml' 

Win8_RU-x64.
 # cobbler profile add --name=Win8-test1 --distro=Win8_RU-x64 --kickstart=/var/lib/cobbler/kickstarts/win.ks --kopts='pxeboot=win81b.0,bootmgr=boot81b.exe,bcd=B8b,winpe=winpb.wim,sif=autounattended01.xml' # cobbler profile add --name=Win8-test2 --distro=Win8_RU-x64 --kickstart=/var/lib/cobbler/kickstarts/win.ks --kopts='pxeboot=win81c.0,bootmgr=boot81c.exe,bcd=B8c,winpe=winpc.wim,sif=autounattended02.xml' 

win.ks :
 #if $profile_name == ' Win8-test1' <code> #end if #if $profile_name == ' Win8-test2' <code> #end if 

, /etc/tftpd.rules . , cobbler sync .

PXE


Cobbler .

- cobbler pxe http_server server.example.org , . Windows , Linux kickstart . :
 # cd /usr/lib/python2.7/site-packages/cobbler # cp templar.py templar.py.orig # sed -i 's/"server.example.org"/self.settings.server/gi' templar.py 

/etc/cobbler/pxe/pxedefault.template
 $pxe_menu_items 

, - :
 menu begin Linux MENU TITLE Linux label Fedora-latest-x86_64 MENU INDENT 5 MENU LABEL Fedora-latest-x86_64 kernel /images/Fedora-22-x86_64/vmlinuz append initrd=/images/Fedora-22-x86_64/initrd.img ks.device=bootif ks.sendmac lang=en text ks=http://@@http_server@@/cblr/svc/op/ks/profile/Fedora-latest-x86_64 ipappend 2 label returntomain menu label Return to ^main menu. menu exit menu end menu begin Windows MENU TITLE Windows label Win8-test1 MENU INDENT 5 MENU LABEL Win8-test1 kernel /winos/Win8_RU-x64/win81b.0 label Win8-test2 MENU INDENT 5 MENU LABEL Win8-test2 kernel /winos/Win8_RU-x64/win81c.0 label returntomain menu label Return to ^main menu. menu exit menu end 


, , wim .

cobbler post sync:
/usr/lib/python2.7/site-packages/cobbler/modules/sync_post_wingen.py
 import distutils.sysconfig import sys import os import traceback import cexceptions import os import re import xmlrpclib import pefile import cobbler.module_loader as module_loader import cobbler.utils as utils import cobbler.config as config import cobbler.templar as templar template_dir = "/var/lib/tftpboot/winos/" sif_template_name = template_dir + "win_sif.template" post_inst_cmd_template_name = template_dir + "post_inst_cmd.template" startnet_template_name = template_dir + "startnet.template" wim7_template_name = template_dir + "winpe7.template" wim8_template_name = template_dir + "winpe8.template" wimlib = "/usr/bin/wimlib-imagex" wimlib_mount = wimlib + " mountrw" wimlib_umount = wimlib + " unmount" mount_point = "/mnt/wim" bcdedit = "/usr/local/bin/bcdedit.pl" plib = distutils.sysconfig.get_python_lib() mod_path="%s/cobbler" % plib sys.path.insert(0, mod_path) def register(): # this pure python trigger acts as if it were a legacy shell-trigger, but is much faster. # the return of this method indicates the trigger type return "/var/lib/cobbler/triggers/sync/post/*" def run( api, args, logger ): settings = api.settings() images = api.images() distros = api.distros() profiles = api.profiles() conf = config.Config( api ) templ = templar.Templar( conf ) rc = 0 template_win = open( post_inst_cmd_template_name ) tmpl_data = template_win.read() template_win.close() for distro in distros: if distro.breed == "windows": meta = utils.blender( api, False, distro ) if distro.kernel_options.has_key( "post_install" ): data = templ.render( tmpl_data, meta, None, distro ) pi_file = open( distro.kernel_options["post_install"], "w+" ) pi_file.write( data ) pi_file.close() template_win = open( sif_template_name ) tmpl_data = template_win.read() template_win.close() template_start = open( startnet_template_name ) tmplstart_data = template_start.read() template_start.close() logger.info( "\nWindows profiles:" ) for profile in profiles: distro = profile.get_conceptual_parent() if distro.breed == "windows": logger.info( 'Profile: ' + profile.name ) meta = utils.blender( api, False, profile ) (distro_path, pxeboot_name) = os.path.split( distro.kernel ) if profile.kernel_options.has_key( "sif" ): data = templ.render( tmpl_data, meta, None, profile ) if distro.os_version in ( "7", "2008", "8", "2012" ): sif_file_name = os.path.join( distro_path, 'sources', profile.kernel_options["sif"] ) else: sif_file_name = os.path.join( distro_path, profile.kernel_options["sif"] ) sif_file = open(sif_file_name, "w+" ) sif_file.write( data ) sif_file.close() logger.info( 'Build answer file: ' + sif_file_name ) if profile.kernel_options.has_key( "pxeboot" ) and profile.kernel_options.has_key( "bootmgr" ): wk_file_name = os.path.join( distro_path, profile.kernel_options["pxeboot"] ) wl_file_name = os.path.join( distro_path, profile.kernel_options["bootmgr"] ) logger.info( "Build PXEBoot: " + wk_file_name ) if distro.os_version in ( "7", "2008", "8", "2012" ): if len(profile.kernel_options["bootmgr"]) != 11: logger.error( "The loader name should be EXACTLY 11 character" ) return 1 if profile.kernel_options.has_key( "bcd" ): if len(profile.kernel_options["bcd"]) != 3: logger.error( "The BCD name should be EXACTLY 5 character" ) return 1 tl_file_name = os.path.join( distro_path, 'bootmgr.exe' ) pat1 = re.compile( r'bootmgr\.exe', re.IGNORECASE ) pat2 = re.compile( r'(\\.Boot\\.)(B)(.)(C)(.)(D)', re.IGNORECASE ) bcd_name = 'BCD' if profile.kernel_options.has_key( "bcd" ): bcd_name = profile.kernel_options["bcd"] bcd_name = "\\g<1>" + bcd_name[0] + "\\g<3>" + bcd_name[1] + "\\g<5>" + bcd_name[2] data = open( tl_file_name, 'rb').read() out = pat2.sub( bcd_name, data ) else: if len(profile.kernel_options["bootmgr"]) != 5: logger.error( "The loader name should be EXACTLY 5 character" ) return 1 if len(profile.kernel_options["sif"]) != 9: logger.error( "The response should be EXACTLY 9 character" ) return 1 tl_file_name = os.path.join( distro_path, 'setupldr.exe' ) pat1 = re.compile( r'NTLDR', re.IGNORECASE ) pat2 = re.compile( r'winnt\.sif', re.IGNORECASE) data = open( tl_file_name, 'rb').read() out = pat2.sub( profile.kernel_options["sif"], data ) logger.info( 'Build Loader: ' + wl_file_name ) if out != data: open(wl_file_name, 'wb+').write(out) if distro.os_version in ( "7", "2008", "8", "2012" ): pe = pefile.PE( wl_file_name, fast_load=True ) pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum() pe.write( filename=wl_file_name ) data = open(distro.kernel, 'rb').read() out = pat1.sub( profile.kernel_options["bootmgr"], data ) if out != data: open(wk_file_name, 'wb+').write(out) if profile.kernel_options.has_key( "bcd" ): obcd_file_name = os.path.join( distro_path, 'boot', 'BCD' ) bcd_file_name = os.path.join( distro_path, 'boot', profile.kernel_options["bcd"] ) wim_file_name = 'winpe.wim' if profile.kernel_options.has_key( "winpe" ): wim_file_name = profile.kernel_options["winpe"] wim_file_name = os.path.join( '/winos', distro.name, 'boot', wim_file_name ) sdi_file_name = os.path.join( '/winos', distro.name, 'boot', 'boot.sdi' ) logger.info( 'Build BCD: ' + bcd_file_name + ' for ' + wim_file_name ) cmd = "/usr/bin/cp " + obcd_file_name + " " + bcd_file_name rc = utils.subprocess_call( logger, cmd, shell=True ) cmd = bcdedit + " " + bcd_file_name + " " + wim_file_name + " " + sdi_file_name rc = utils.subprocess_call( logger, cmd, shell=True ) ps_file_name = os.path.join( distro_path, "boot", profile.kernel_options["winpe"] ) if distro.os_version in ( "7", "2008" ): wim_pl_name = wim7_template_name elif distro.os_version in ( "8", "2012" ): wim_pl_name = wim8_template_name cmd = "/usr/bin/cp " + wim_pl_name + " " + ps_file_name rc = utils.subprocess_call( logger, cmd, shell=True ) if os.path.exists( wimlib ): cmd = wimlib_mount + " " + ps_file_name + " " + mount_point rc = utils.subprocess_call( logger, cmd, shell=True ) data = templ.render( tmplstart_data, meta, None, profile ) pi_file = open( mount_point + "/Windows/System32/startnet.cmd", "w+" ) pi_file.write( data ) pi_file.close() cmd = wimlib_umount + " " + mount_point + " --commit --rebuild" rc = utils.subprocess_get( logger, cmd, shell=True ) return 0 


python Cobbler API. pefile bootmgr.exe, bcdedit.pl BCD wimlib startnet.cmd Windows/System32.

:
 # mkdir /mnt/wim # systemctl restart cobblerd # cobbler sync # systemctl restart xinetd 

, Reset, F12 ( BIOS ), Linux Windows.

win.ks. , if/else:
 #if $profile_name == '<profile_name1>' <code> #elseif $profile_name == '<profile_name2>' <code> . . . #elseif $profile_name == '<profile_nameN>' <code> #end if 

, .


  1. Windows . Microsoft , .
  2. ( ) ISO Windows .
  3. PXE cobbler Windows .
  4. , /etc/tftpd.rules. , .

Source: https://habr.com/ru/post/263883/


All Articles