[Patch] zuverlässigere Netzwerkinstallation
Verfasst: 05 Jun 2013, 19:46
Hi,
wir haben bei Windows 7-Installationen früher häufiger die Erfahrung gemacht, dass Installationen mit aktiver Netzwerkinstallation (winpeNetworkMode=True) bei unseren Kunden trotz vorhandener Netzwerktreiber fehlschlagen. Die Ursache ist, dass die Netzwerkinstallation für alle Netzwerkkartentreiber, die von der ID her zur Netzwerkkarte passen, drvload-Anweisungen in die work.cmd einfügt:
Es kann passieren, dass auf die Art und Weise zuerst ein funktionierender Treiber geladen wird, der anschließend direkt durch einen nicht funktionierenden Treiber ersetzt wird. Anschließend versucht das Script, die Freigabe zu mounten, was natürlich fehlschlägt; dann wiederholt es alle drvload-Anweisungen, was das Problem natürlich nicht löst. Infolgedessen haben wir die Netzwerkinstallation in unserem Windows 7-Paket dann einfach komplett entfernt, um diesem Fehler vorzubeugen.
Bei Windows 8 sind wir aber jetzt auf die Netzwerkinstallation angewiesen. Bei Windows 7 hatten wir nämlich die install.wim in mehrere *.swm-Images aufgeteilt, weil Debian nicht richtig mit deb-Paketen > 2 GB zurechtkommt; dieses Feature hat Microsoft bei Windows 8 aus unbekannten Gründen entfernt, sodass wir das Image für Windows 8 nicht mehr splitten können. Da unser Image mit integrierten Updates aber > 4 GB groß ist, ist es jetzt auch zu groß für die FAT32-Partition, die von opsi für die Installation verwendet wird.
Daher habe ich die Netzwerkinstallation in unserem Windows 8-Paket so umgeschrieben, dass er die verfügbaren Treiber in einer Schleife durchläuft, und sie einzeln ausprobiert:
Die entsprechenden Änderungen an der setup.py wollte ich eigentlich an dieses Posting anhängen, aber das Forum erlaubt es nicht 
Eine von diesem Code erzeugte work.cmd sieht z. B. so aus:
Produktiv im Einsatz war das Ganze noch nicht, aber bei mir im Test scheint es gut zu funktionieren.
wir haben bei Windows 7-Installationen früher häufiger die Erfahrung gemacht, dass Installationen mit aktiver Netzwerkinstallation (winpeNetworkMode=True) bei unseren Kunden trotz vorhandener Netzwerktreiber fehlschlagen. Die Ursache ist, dass die Netzwerkinstallation für alle Netzwerkkartentreiber, die von der ID her zur Netzwerkkarte passen, drvload-Anweisungen in die work.cmd einfügt:
Code: Alles auswählen
drvload <Treiber 1>
drvload <Treiber 2>
...
mount
setup
Bei Windows 8 sind wir aber jetzt auf die Netzwerkinstallation angewiesen. Bei Windows 7 hatten wir nämlich die install.wim in mehrere *.swm-Images aufgeteilt, weil Debian nicht richtig mit deb-Paketen > 2 GB zurechtkommt; dieses Feature hat Microsoft bei Windows 8 aus unbekannten Gründen entfernt, sodass wir das Image für Windows 8 nicht mehr splitten können. Da unser Image mit integrierten Updates aber > 4 GB groß ist, ist es jetzt auch zu groß für die FAT32-Partition, die von opsi für die Installation verwendet wird.
Daher habe ich die Netzwerkinstallation in unserem Windows 8-Paket so umgeschrieben, dass er die verfügbaren Treiber in einer Schleife durchläuft, und sie einzeln ausprobiert:
Code: Alles auswählen
if mount then setup (erster Versuch mit integrierten Treibern)
drvload <Treiber 1>
if mount then setup
drvload <Treiber 2>
if mount then setup
...
error

Dann halt als Text:Das Kontingent für Dateianhänge ist bereits vollständig ausgenutzt.
Code: Alles auswählen
--- setup.py.orig2 2013-06-05 19:37:06.000000000 +0200
+++ setup.py 2013-06-05 19:16:00.000000000 +0200
@@ -426,12 +426,22 @@
logger.notice("Creating work.cmd")
f = open(target + '/opsi/work.cmd', 'w')
print >> f, "@echo off\r"
+ print >> f, "\r"
+ print >> f, "rem http://superuser.com/questions/80485/exit-batch-file-from-subroutine"
+ print >> f, "setlocal\r"
+ print >> f, "IF \"%selfWrapped%\"==\"\" (\r"
+ print >> f, " REM this is necessary so that we can use \"exit\" to terminate the batch file,\r"
+ print >> f, " REM and all subroutines, but not the original cmd.exe\r"
+ print >> f, " SET selfWrapped=true\r"
+ print >> f, " %ComSpec% /s /c \"\"%~0\" %*\"\r"
+ print >> f, " GOTO :EOF\r"
+ print >> f, ")\r"
+ print >> f, "\r"
print >> f, "copy c:\\opsi\\unattend.xml x:\\unattend.xml >nul\r"
- print >> f, ":init\r"
- print >> f, "set mount_try_count=0\r"
print >> f, "c:\\opsi\\SetWallpaper.exe c:\\opsi\\opsibg.bmp >nul 2>nul\r"
print >> f, "echo Initializing ..... please wait ......\r"
print >> f, "wpeinit\r"
+ print >> f, "\r"
if winpeNetworkMode and (depot._url.startswith('smb:') or depot._url.startswith('cifs:')):
match = re.search('^smb://([^/]+)/([^/]+)(.*)$', depot._url, re.IGNORECASE)
@@ -441,8 +451,7 @@
sn = match.group(2)
pn = match.group(3)
- print >> f, "goto mountshare\r"
- print >> f, ":drvloadnetwork\r"
+ drivers = []
if os.path.exists(dstDriversDir):
storageControllerInfo = disk.getControllerInfo()
for filePath in findFiles(prefix = dstDriversDir, directory = dstDriversDir, includeFile = re.compile('\.inf$', re.IGNORECASE), returnDirs = False):
@@ -454,33 +463,54 @@
filePath = filePath[1:]
filePath = 'c:\\' + filePath.replace('/', '\\')
logger.notice("Adding to work.cmd: drvload %s\r" % filePath )
- print >> f, "drvload %s\r" % filePath
+ drivers.append(filePath)
if storageControllerInfo and infFile.isDeviceKnown(storageControllerInfo['vendorId'], storageControllerInfo['deviceId']):
logger.info(u"Integrating winpe driver for storage controller: %s" % storageControllerInfo)
copy(os.path.dirname(filePath), dstPeDriversDir)
+ driversstr = ",".join(drivers)
encodedPcpatchPassword = backend.getPcpatchPassword(hostId = clientId)
- print >> f, "goto mountshare\r"
- print >> f, ":waitnet\r"
- print >> f, "echo Waiting for the network ......\r"
- print >> f, "ping -n 5 127.0.0.1 >nul\r"
- print >> f, ":mountshare\r"
- print >> f, "set /a mount_try_count=%mount_try_count%+1\r"
- print >> f, "net use /y /delete * >nul\r"
- print >> f, "ping -n 5 127.0.0.1 >nul\r"
- print >> f, "c:\\opsi\\opsinetmount.exe --keyfile=c:\\opsi\\opsi-client-agent\\files\\opsi\\cfg\\config.ini --user=%s\\pcpatch --drive=o --share=\\\\%s\\%s --encrypted-pass=%s \r" % (hn, hn, sn, encodedPcpatchPassword)
- print >> f, "if not %ERRORLEVEL%==0 (\r"
- print >> f, " if %mount_try_count%==5 goto drvloadnetwork\r"
- print >> f, " if %mount_try_count%==15 goto init\r"
- print >> f, " goto waitnet\r"
- print >> f, ")\r"
- print >> f, ":install\r"
- print >> f, "o:%s\\%s\\installfiles\\setup.exe %s" % (pn.replace('/', '\\'), productId, "/unattend:x:\\unattend.xml\r")
- else:
- print >> f, ":install\r"
- print >> f, "c:\\installfiles\\setup.exe /unattend:x:\\unattend.xml\r"
- print >> f, "if not %ERRORLEVEL%==0 goto init\r"
+ print >> f, "set attempts=1\r"
+ print >> f, "call :iter\r"
+ print >> f, "call :list_iter :iter \"%s\"\r" % driversstr
+ print >> f, "set attempts=5\r"
+ print >> f, "call :iter\r"
+ print >> f, "call :list_iter :iter \"%s\"\r" % driversstr
+ print >> f, "echo.\r"
+ print >> f, "echo Kein passender Netzwerktreiber gefunden!\r"
+ print >> f, "echo Bitte kopieren Sie den richtigen Netzwerktreiber nach \\\\iserv\\driver\r"
+ print >> f, "echo und starten Sie die Installation neu.\r"
+ print >> f, "echo.\r"
+ print >> f, "pause\r"
+ print >> f, "exit /b\r"
+ print >> f, "\r"
+ print >> f, ":iter\r"
+ print >> f, " if not \"%*\"==\"\" drvload %*\r"
+ print >> f, " call :mount || exit /b 1\r"
+ print >> f, " o:%s\\%s\\installfiles\\setup.exe %s" % (pn.replace('/', '\\'), productId, "/unattend:x:\\unattend.xml\r")
+ print >> f, " exit\r"
+ print >> f, "\r"
+ print >> f, ":mount\r"
+ print >> f, " for /l %%a in (1,1,%attempts%) do (\r"
+ print >> f, " if not %attempts%==1 echo Mountversuch %%a von %attempts%\r"
+ print >> f, " net use /y /delete * >nul\r"
+ print >> f, " ping -n 5 127.0.0.1 >nul\r"
+ print >> f, " c:\\opsi\\opsinetmount.exe --keyfile=c:\\opsi\\opsi-client-agent\\files\\opsi\\cfg\\config.ini --user=%s\\pcpatch --drive=o --share=\\\\%s\\%s --encrypted-pass=%s && exit /b\r" % (hn, hn, sn, encodedPcpatchPassword)
+ print >> f, " ping -n 5 127.0.0.1 >nul\r"
+ print >> f, " )\r"
+ print >> f, " exit /b 1\r"
+ print >> f, "\r"
+ print >> f, "rem http://stackoverflow.com/questions/2524928/dos-batch-iterate-through-a-delimited-string\r"
+ print >> f, ":list_iter\r"
+ print >> f, " rem Usage: call :list_iter :do_sub_for_each_item \"CSV of items\"\r"
+ print >> f, " set foo=%1\r"
+ print >> f, " set list=%~2\r"
+ print >> f, " for /f \"tokens=1* delims=,\" %%i in (\"%list%\") do (\r"
+ print >> f, " call %foo% %%i\r"
+ print >> f, " if not \"%%j\" == \"\" ( call :list_iter %foo% \"%%j\" )\r"
+ print >> f, " )\r"
+ print >> f, " exit /b\r"
f.close()
# Create startnet.cmd
Code: Alles auswählen
@echo off
rem http://superuser.com/questions/80485/exit-batch-file-from-subroutine
setlocal
IF "%selfWrapped%"=="" (
REM this is necessary so that we can use "exit" to terminate the batch file,
REM and all subroutines, but not the original cmd.exe
SET selfWrapped=true
%ComSpec% /s /c ""%~0" %*"
GOTO :EOF
)
copy c:\opsi\unattend.xml x:\unattend.xml >nul
c:\opsi\SetWallpaper.exe c:\opsi\opsibg.bmp >nul 2>nul
echo Initializing ..... please wait ......
wpeinit
set attempts=1
call :iter
call :list_iter :iter "c:\drv\7\e1c62x64.inf,c:\drv\8\e1c60x64.inf,c:\drv\9\e1c62x64.inf,c:\drv\10\e1c63x64.inf,c:\drv\11\e1c60x64.inf,c:\drv\12\e1c63x64.inf"
set attempts=5
call :iter
call :list_iter :iter "c:\drv\7\e1c62x64.inf,c:\drv\8\e1c60x64.inf,c:\drv\9\e1c62x64.inf,c:\drv\10\e1c63x64.inf,c:\drv\11\e1c60x64.inf,c:\drv\12\e1c63x64.inf"
echo.
echo Kein passender Netzwerktreiber gefunden!
echo Bitte kopieren Sie den richtigen Netzwerktreiber nach \\iserv\driver
echo und starten Sie die Installation neu.
echo.
pause
exit /b
:iter
if not "%*"=="" drvload %*
call :mount || exit /b 1
o:\install\microsoft-windows-8-64\installfiles\setup.exe /unattend:x:\unattend.xml
exit
:mount
for /l %%a in (1,1,%attempts%) do (
if not %attempts%==1 echo Mountversuch %%a von %attempts%
net use /y /delete * >nul
ping -n 5 127.0.0.1 >nul
c:\opsi\opsinetmount.exe --keyfile=c:\opsi\opsi-client-agent\files\opsi\cfg\config.ini --user=iserv\pcpatch --drive=o --share=\\iserv\deploy --encrypted-pass=entfernt && exit /b
ping -n 5 127.0.0.1 >nul
)
exit /b 1
rem http://stackoverflow.com/questions/2524928/dos-batch-iterate-through-a-delimited-string
:list_iter
rem Usage: call :list_iter :do_sub_for_each_item "CSV of items"
set foo=%1
set list=%~2
for /f "tokens=1* delims=," %%i in ("%list%") do (
call %foo% %%i
if not "%%j" == "" ( call :list_iter %foo% "%%j" )
)
exit /b
Produktiv im Einsatz war das Ganze noch nicht, aber bei mir im Test scheint es gut zu funktionieren.