setup.py

Antworten
IWW_sebastian
Beiträge: 28
Registriert: 02 Jan 2013, 13:59

setup.py

Beitrag von IWW_sebastian »

Hi Leute,

ich habe versucht die setup.py für eine Windows 7-X64 Installation anzupassen.
Leider scheint da so einiges schief zu gehen.
In der mitgelieferten Version werden ja mehrere Partitionen angelegt, danach der Rechner heruntergefahren und von der PE-Partition gebootet, auf der vor verschiedene Treiber abgelegt wurden. -> Diese Treiber werden beim nächsten Neustart automatisch geladen, ein Netzlaufwerk wird gemountet und die restl. Windows-Dateien werden für die Installation nachgezogen, wobei die gesamte Partitionierung dann wie folgt aussieht:

X:(Windows)->C:(PE,aktiv,lba)->(DataPartition)->unallozierter Speicherplatz

Meine Idee war aber automatisch eine weitere Partition durch die setup.py erzeugen zu lassen, die hinter der DataPartition liegt:
der Code sieht dafür wie folgt aus:

Code: Alles auswählen

#
# This script requires opsi >= 4.0, opsi-linux-bootimage version >= 20111114
#
#alle Groeßen standardmaeßig in byte -> sollte in MB angegeben sein, so ist dies durch das Kuerzel M am VariablenNamen angegeben

if not bootimageVersion or (int(bootimageVersion) < 20111114):
    raise Exception(u"This product requires opsi-linux-bootimage version 20111114")
try:
    if not backend.isOpsi4():
        raise Exception
except:
    raise Exception(u"This is a opsi 4.0 product")

modifyPartitions = []
modifyPartitionTemplate = \
'''
<ModifyPartition wcm:action="add">
    <Active>%(active)s</Active>
    <Format>%(format)s</Format>
    <Label>%(label)s</Label>
    <Letter>%(letter)s</Letter>
    <Extend>false</Extend>
    <Order>%(order)s</Order>
    <PartitionID>%(partition)s</PartitionID>
</ModifyPartition>
'''

target = '/mnt/hd'
source = SCRIPT_PATH
srcDriversDir = source + '/drivers'
dstDriversDir = target + '/drv'
dstPeDriversDir = target + '/drvpe'
winpeNetworkMode = True

bootPartitionNumber = 0
bootPartitionSize   = productProperties.get('boot_partition_size', '0')
bootPartitionLabel  = productProperties.get('boot_partition_label', 'BOOT')
bootPartitionLetter = "S"
bootPartitionHidden = True
if (productProperties.get('boot_partition_letter', '-') != '-'):
    bootPartitionLetter = productProperties.get('boot_partition_letter')
    bootPartitionHidden = False

windowsPartitionNumber = 1
windowsPartitionSize   = productProperties.get('windows_partition_size','100%')
windowsPartitionLabel  =productProperties.get('windows_partition_label', 'WINDOWS')
windowsPartitionLetter = "C"

winpePartitionNumber = 2
winpePartitionSize   = "4000M"
winpePartitionLabel  = "WINPE"
winpePartitionLetter = "X"

#Hole dir die Eigenschaften der D:\ Partition
dataPartitionNumber = 0
datapartioncreate   = productProperties.get('data_partition_create', true)
dataPartitionSize   = productProperties.get('data_partition_size', 20480)
dataPartitionLabel  = productProperties.get('data_partition_label', 'DATA')
dataPartitionLetter = productProperties.get('data_partition_letter', 'D')

#Hole dir die Eigenschaften von E:\
#Idee: aktiviere die Spare-Partition nur, wenn!! diese als aktiviert angegeben ist
sparePartitionNumber = 0 
sparepartioncreate   = productProperties.get('spare_partition_create', true)
sparePartitionSize   = productProperties.get('spare_partition_size', '100%')
sparePartitionLabel  = productProperties.get('spare_partition_label', 'Spielwiese')
sparePartitionLetter = productProperties.get('spare_partition_letter', 'E')

blockAlignment = False
if (str(productProperties.get('blockAlignment', 'true')).lower() == 'true'):
    blockAlignment = True
   
if (str(productProperties.get('winpenetworkmode', 'true')).lower() == 'false'):
    winpeNetworkMode = False
#Abfrage eigentlich sinnlos, weil unsere Installation immer zwingend eine D:\ Partition vorraussetzt
if (windowsPartitionSize != "100%" and datapartioncreate):
    dataPartitionNumber = 3
	if (sparepartioncreate):
	   sparePartitionNumber = 4

activePartition = "true"
if not bootPartitionSize.startswith("0"):
    bootPartitionNumber = 1
    windowsPartitionNumber += 1
    winpePartitionNumber += 1
    if (dataPartitionNumber > 0):
       dataPartitionNumber += 1
    if (sparePartitionNumber > 0):
       sparePartitionNumber += 1
    modifyPartitions.append(
        modifyPartitionTemplate % {
            "active":    activePartition,
            "format":    "NTFS",
            "label":     bootPartitionLabel,
            "letter":    bootPartitionLetter.upper(),
            "order":     len(modifyPartitions) + 1,
            "partition": bootPartitionNumber,
        }
    )
    activePartition = "false"

modifyPartitions.append(
    modifyPartitionTemplate % {
        "active":    activePartition,
        "format":    "NTFS",
        "label":     windowsPartitionLabel,
        "letter":    windowsPartitionLetter.upper(),
        "order":     len(modifyPartitions) + 1,
        "partition": windowsPartitionNumber,
    }
)

modifyPartitions.append(
    modifyPartitionTemplate % {
        "active":    "false",
        "format":    "",
        "label":     winpePartitionLabel,
        "letter":    winpePartitionLetter.upper(),
        "order":     len(modifyPartitions) + 1,
        "partition": winpePartitionNumber,
    }
)

if (dataPartitionNumber > 0):
    modifyPartitions.append(
        modifyPartitionTemplate % {
            "active":    "false",
            "format":    "NTFS",
            "label":     dataPartitionLabel,
            "letter":    dataPartitionLetter.upper(),
            "order":     len(modifyPartitions) + 1,
            "partition": dataPartitionNumber,
        }
    )
#lege hier genauso die Spare-Partition als Objekt an	
if (sparePartitionNumber > 0):
    modifyPartitions.append(
        modifyPartitionTemplate % {
            "active":    "false",
            "format":    "NTFS",
            "label":     sparePartitionLabel,
            "letter":    sparePartitionLetter.upper(),
            "order":     len(modifyPartitions) + 1,
            "partition": sparePartitionNumber,
        }
    )


pi = open(PATCHA_IN, 'a')
print >> pi, "windows_partition_number=%d" % windowsPartitionNumber
print >> pi, "winpe_partition_letter=%s" % winpePartitionLetter.upper()
print >> pi, "modify_partitions=%s" %''.join(modifyPartitions).replace('\n', '').replace('<Format></Format>', '')
pi.close()

# Do hardware inventory
logger.notice(u"Fetching opsi hw audit configuration")
hwconfig = backend.auditHardware_getConfig()

logger.notice(u"Running hardware inventory")
auditHardwareOnHosts = auditHardware(config = hwconfig, hostId = clientId)

logger.notice(u"Sending hardware information to service")
backend.auditHardwareOnHost_setObsolete(clientId)
backend.auditHardwareOnHost_updateObjects(auditHardwareOnHosts)

# Get harddisks
disks = getHarddisks()

# Use first Harddisk
disk = disks[0]
if blockAlignment:
    disk.setBlockAlignment(blockAlignment)
scriptMessageSubject.setMessage(u"Verwende Festplatte %s (%0.0f MB)." %(disk.device, (float(disk.size)/(1024*1024))))

# Check disk size
if (disk.size < 85000*1024*1024):
     #Disk smaller than 85000 MB => give up, Anpassung fuers IWW
     raise Exception(u"Die Festplatte ist zu klein")

# Get current partitions
partitions = disk.getPartitions()

if not partitions:
    # No partition found on harddisk
    scriptMessageSubject.setMessage(u"Keine Partitionen auf %s gefunden" % disk.device)
   
# Create new partitiontable
disk.deletePartitionTable()

# Partition table deleted => delete all netboot product states
backend.backend_setOptions( { 'addProductPropertyStateDefaults': False } )
deletePocs = []
for poc in backend.productOnClient_getObjects(clientId = clientId):
	if ((poc.productType == 'NetbootProduct') and (poc.productId != productId)) or \
	   ((poc.productType == 'LocalbootProduct') and (poc.installationStatus == 'not_installed') and (poc.actionRequest == 'none')):
		deletePocs.append(poc)
backend.productOnClient_deleteObjects(deletePocs)

# Create partitions
diskSizeM = (float(disk.size)/(1024*1024)) #Angabe in MB
diskTotalSectors = disk.sectors
bootPartitionSizeM = 0
if not bootPartitionSize.startswith("0"):
    # Create boot partition
    if not blockAlignment:
        disk.createPartition(start = "0M", end = bootPartitionSize, fs ="ntfs")
        bootPartitionSizeM = int(bootPartitionSize.upper().replace('M','').replace('G', '').replace('B', ''))
        if (bootPartitionSize.upper().find('G') != -1):
            bootPartitionSizeM *= 1024
        logger.notice(u"Boot partition (%d) size is %dM" %(bootPartitionNumber, bootPartitionSizeM))
    else:
        disk.createPartition(start = "2048S", end = bootPartitionSize, fs = "ntfs")
        bootPartitionSizeM = int(bootPartitionSize.upper().replace('M','').replace('G', '').replace('B', ''))
        if (bootPartitionSize.upper().find('G') != -1):
            bootPartitionSizeM *= 1024
        logger.notice(u"Boot partition (%d) size is %dM" % (bootPartitionNumber, bootPartitionSizeM))
peStartM = int(diskSizeM - 4000)
boundaryM = int(diskSizeM)

if (windowsPartitionSize != "100%"):
    sizeM = 0
    if (windowsPartitionSize.find('%') != -1):
        percent = int(windowsPartitionSize.replace('%', ''))
        windowsPartitionSizeM =int((float(percent)/100.0)*float(diskSizeM-bootPartitionSizeM))
    else:
        windowsPartitionSizeM = int(windowsPartitionSize.upper().replace('M','').replace('G', '').replace('B', ''))
        if (windowsPartitionSize.upper().find('G') != -1):
            windowsPartitionSizeM *= 1024
    dataSizeM = diskSizeM - windowsPartitionSizeM
    logger.notice(u"Windows partiton (%s) size is %dM, data partition (%d) size is %dM" \
        % (windowsPartitionNumber, windowsPartitionSizeM, dataPartitionNumber, dataSizeM))
    if (dataSizeM <= 0):
        raise Exception(u"Not enough disk space for windows partiton size %dM" % windowsPartitionSizeM)
    boundaryM = bootPartitionSizeM + windowsPartitionSizeM
    peStartM = boundaryM - 4000

# Create windows partition
disk.createPartition(start = "%dM" % bootPartitionSizeM, end = "%dM" % peStartM, fs = "ntfs")

# Create winpe partition
disk.createPartition(start = "%dM" % peStartM, end = "%dM" % boundaryM, fs = "fat32", boot = True)

if (dataPartitionNumber > 0):
		#Berechne als erstes die Groeße der D:\ Partition in ganzen MB
		if (dataPartitionSize.find('%') != -1):
			percent = int(dataPartitionSize.replace('%', ''))
			dataPartitionsizeM =int((float(percent)/100.0)*float(diskSizeM-bootPartitionSizeM-windowsPartitionSizeM))
		else:
			dataPartitionsizeM = int(dataPartitionSize.upper().replace('M','').replace('G', '').replace('B', ''))
			if (dataPartitionSize.upper().find('G') != -1):
				dataPartitionsizeM *= 1024		
        #sollte ausreichend  Platz auf der Platte sein, um die volle 20GB Partition anzulegen
        if ((boundaryM + dataPartitionSizeM) <= diskSizeM):
            # Create data partition
            disk.createPartition(start = "%dM" % boundaryM, end = "%dM" % (boundaryM + dataPartitionSizeM), fs = "ntfs")
			#wenn noch Platz ist, verschiebe jetzt die BoundaryM um die Groeße der Datenpartition
			boundaryM += dataPartitionSizeM
        #Falls ueberhaupt kein Platz mehr auf der platte sein sollte, so schreibe das in log, werfe eine Exception und deaktivere die E:\ Partition
        elif((boundaryM - diskSizeM) > 0):
            logger.notice(u"Es steht auf der ersten Platte nicht genug Speicher fuer D:\ zur Verfuegung")
			raise Exception(u"Problem, absolut kein Platz mehr fuer D:\ auf der Platte")
			sparePartitionNumber = 0
        #ansonsten lege die max. moegliche große Partition D:\ an
        else:
             disk.createPartition(start = "%dM" % boundaryM, end = "%dM" % diskSizeM, fs = "ntfs")   
			 #Deaktivere die sparePartition E: 
			 sparePartitionNumber = 0	

#lege jetzt die SparePartition an, aber nur, wenn vorher D:\ in voller Groeße angelegt werden konnte			 
if (sparePartitionNumber > 0):
		#Berechne als erstes die Groeße der D:\ Partition in ganzen MB
		if (sparePartitionSize.find('%') != -1):
			percent = int(sparePartitionSize.replace('%', ''))
			sparePartitionSizeM =int((float(percent)/100.0)*float(diskSizeM-bootPartitionSizeM-windowsPartitionSizeM-dataPartitionSizeM))
		else:
			sparePartitionsizeM = int(sparePartitionSize.upper().replace('M','').replace('G', '').replace('B', ''))
			if (sparePartitionSize.upper().find('G') != -1):
				sparePartitionsizeM *= 1024		
        #sollte ausreichend  Platz auf der Platte sein, um die volle 20GB Partition anzulegen
        if ((boundaryM + sparePartitionSizeM) <= diskSizeM):
            # Create data partition
            disk.createPartition(start = "%dM" % boundaryM, end = "%dM" % (boundaryM + sparePartitionSizeM), fs = "ntfs")
        #Falls ueberhaupt kein Platz mehr auf der platte sein sollte, so schreibe das in log, lege kein E:\ an
        elif((boundaryM - diskSizeM) > 0):
            logger.notice(u"Es steht auf der ersten Platte nicht genug Speicher fuer E:\ zur Verfuegung")
        #ansonsten lege die max. moegliche große Partition E:\ an
        else:
             disk.createPartition(start = "%dM" % boundaryM, end = "%dM" % diskSizeM, fs = "ntfs")   
			
partitions = disk.getPartitions()


# Create fat32 filesystem on winpe partition
disk.createFilesystem(partition = winpePartitionNumber, fs = "fat32")

if (dataPartitionNumber > 0):
    # Create ntfs filesystem on data partition
    disk.createFilesystem(partition = dataPartitionNumber, fs = "ntfs")
	
if (sparePartitionNumber > 0):
    # Create ntfs filesystem on data partition
    disk.createFilesystem(partition = sparePartitionNumber, fs = "ntfs")

# Write Master Boot Record
disk.writeMasterBootRecord(system = 'vista')

# Write Partition Boot Record
disk.writePartitionBootRecord(partition = winpePartitionNumber, fsType ='fat32nt60')

# Mount partition
disk.mountPartition(partition = winpePartitionNumber, mountpoint = target)

# Copy PE files
depot.copy(source + '/winpe/*', target)
if not os.path.exists(os.path.join(target, 'bootmgr')):
    raise Exception("bootmgr not found in winpe, please check winpe folder on server")

# Copy Windows installation files
if not winpeNetworkMode:
    depot.copy(source + '/installfiles', target)

# Copy opsi files
depot.copy(source + '/opsi', target + '/')

# Copy opsi-client-agent
depot.copy('/opsi-client-agent', target + '/opsi/')
copy(target + '/opsi/opsi-client-agent/files/opsi/postinst.d/*', target + '/opsi/postinst.d/')

# Copy custom files
depot.copy(source + '/custom/unattend.xml', target + '/opsi/')
depot.copy(source + '/custom/postinst.d/*', target + '/opsi/postinst.d/')

# Copy sysconf.ini to opsi-client-agent config dir
copy(SYSCONF_INI , target + '/opsi/opsi-client-agent/files/opsi/cfg')

# Integrate drivers
os.makedirs(dstDriversDir)
os.makedirs(dstPeDriversDir)
if depot.exists(srcDriversDir):
    scriptMessageSubject.setMessage("Treiber-Verzeichnis '%s' gefunden, starte Treiberintegration" % srcDriversDir)
    additionalDrivers = [ ad.strip() for ad in(u','.join(productPropertyValues.get('additional_drivers',[u'']))).split(u',') ]
    integrateAdditionalWindowsDrivers(srcDriversDir + u'/drivers/additional', dstDriversDir, additionalDrivers, messageSubject = scriptMessageSubject, srcRepository = depot, auditHardwareOnHosts = auditHardwareOnHosts)
    integrateWindowsHardwareDrivers(srcDriversDir, dstDriversDir, auditHardwareOnHosts, messageSubject = scriptMessageSubject, srcRepository = depot)

# Create work.cmd
logger.notice("Creating work.cmd")
f = open(target + '/opsi/work.cmd', 'w')
print >> f, "@echo off\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"

if winpeNetworkMode and (depot._url.startswith('smb:') or depot._url.startswith('cifs:')):
	match = re.search('^smb://([^/]+)/([^/]+)(.*)$', depot._url, re.IGNORECASE)
	if not match:
		raise Exception("Bad depot-URL '%s'" % depot._url)
	hn = match.group(1)
	sn = match.group(2)
	pn = match.group(3)
	
	print >> f, "goto mountshare\r"
	print >> f, ":drvloadnetwork\r"
	if os.path.exists(dstDriversDir):
		storageControllerInfo = disk.getControllerInfo()
		for filePath in findFiles(prefix = dstDriversDir, directory = dstDriversDir, includeFile = re.compile('\.inf$', re.IGNORECASE), returnDirs = False):
			infFile = InfFile(filePath)
			if infFile.isDeviceKnown(usedNetworkDevice['vendorId'], usedNetworkDevice['deviceId']):
				logger.info(u"Integrating winpe driver for network controller: %s" % usedNetworkDevice)
				filePath = filePath[len(target):]
				if filePath.startswith('/'):
					filePath = filePath[1:]
				filePath = 'c:\\' + filePath.replace('/', '\\')
				logger.notice("Adding to work.cmd: drvload %s\r" % filePath )
				print >> f, "drvload %s\r" % 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)
	
	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"
f.close()

# Create startnet.cmd
logger.notice(u"Creating startnet.cmd")
f = open(target + '/opsi/startnet.cmd', 'w')
print >> f, "@echo off\r"
print >> f, "copy c:\\opsi\\work.cmd x:\\work.cmd >nul\r"
print >> f, "x:\\work.cmd"
f.close()

# Create diskpart.txt
logger.notice(u"Creating diskpart.txt")
f = open(target + '/opsi/diskpart.txt', 'w')
f = open(target + '/opsi/diskpart.txt', 'w')
print >> f, "list disk\r"
print >> f, "select disk 0\r"
print >> f, "list partition\r"
print >> f, "list volume\r"
print >> f, "select partition %d\r" % winpePartitionNumber
print >> f, "delete partition noerr override\r"
print >> f, "select partition %d\r" % (winpePartitionNumber - 1)
print >> f, "extend\r"
if bootPartitionNumber and bootPartitionHidden:
	print >> f, "select volume %s\r" % bootPartitionLetter
	print >> f, "remove letter=%s\r" % bootPartitionLetter
print >> f, "exit\r"
f.close()

# Patch files
logger.notice(u"Patching unattend.xml and config.ini")
for i in ( target + '/opsi/unattend.xml', target + '/opsi/opsi-client-agent/files/opsi/cfg/config.ini' ):
    execute('/usr/local/bin/patcha %s' % i)
    execute('/usr/local/bin/patcha -f %s %s' % (PATCHA_IN, i))

# Debug output of file content
for fn in ('/opsi/work.cmd', '/opsi/startnet.cmd', '/opsi/diskpart.txt'):
    execute("%s '%s'" % (which('cat'), target + fn))

# Umount partition
disk.umountPartition(partition = winpePartitionNumber)

# Reboot
reboot()
Wenn ich diese setup.py verwende, werden auch die entsprechenden Partitionen erzeugt, startnet.cmd und work.cmd werden an den richtigen Stellen abgelegt und auch die Treiber inf wird rüberkopiert.
die Partitionen sehen dann wie folgt aus:

X:(Windows)->C:(PE,aktiv,lba)->(DataPartition)->(SparePartition)

Leider funktionieren hier jedoch die startnet.cmd und die work.cmd nicht mehr. Da ich nur noch folgende Fehlermeldung im Dosfenster erhalte:
Waiting for Network
Systemfehler 1222 aufgetreten
Das Netzwerk ist nicht vorhanden oder wurde nicht gestartet
mountresult: 1222: Das Netzwerk ist nicht vorhanden oder wurde nicht gestartet


Hat jemand eine Idee, woher dieser Fehler resultiert?
Liegt der Fehler in meinem angepassten Script? Oder ist das eine interne Beschränkung von OPSI?

Besten Dank für eure Antworten

Sebastian
IWW_sebastian
Beiträge: 28
Registriert: 02 Jan 2013, 13:59

Re: setup.py

Beitrag von IWW_sebastian »

Hi,

leider scheint ja keiner eine Idee zu haben .... hat vielleicht mal jemand selbst die Setup.py so angepasst, dass am Ende 3 Partitionen auf der Festplatte stehen bleiben?
(Am besten so, dass man die Größen anpassen kann)


Danke, Sebastian
uncle_scrooge
Beiträge: 650
Registriert: 21 Feb 2012, 12:03
Wohnort: Mainz

Re: setup.py

Beitrag von uncle_scrooge »

Von der Meldung her sieht es ja wohl nach fehlendem NIC-Treiber aus.
Was gibt die Logdatei (bootimage) her? (Bereich driver integration)
Finden sich auf C: die Verzeichnisse \drv und drvpe? Wenn ja, auch mit Inhalt?
IWW_sebastian
Beiträge: 28
Registriert: 02 Jan 2013, 13:59

Re: setup.py

Beitrag von IWW_sebastian »

das hing nur indirekt mit den NIC-Treibern zusammen, da diese schon vorhanden waren, jedoch hatte ich in der Struktur modifyPartitions wohl einen Fehler eingebaut, der sich dann in folgendes Codesegment ausgeweitet hat:

Code: Alles auswählen

pi = open(PATCHA_IN, 'a')
print >> pi, "windows_partition_number=%d" % windowsPartitionNumber
print >> pi, "winpe_partition_letter=%s" % winpePartitionLetter.upper()
print >> pi, "modify_partitions=%s" %''.join(modifyPartitions).replace('\n', '').replace('<Format></Format>', '')
pi.close()
Ich weiß immer noch nicht, was dieses Stück Code eigentlich macht, aber nachdem ich den Fehler in der modifyPartitions.append Sektion behoben hatte, funktionierte alles einwandfrei:
Ach ja, und wen es interessiert, hier der korrigierte Code:

Code: Alles auswählen

#
# This script requires opsi >= 4.0, opsi-linux-bootimage version >= 20111114
#
#alle Groessen standardmaessig in byte -> sollte in MB angegeben sein, so ist dies durch das Kuerzel M am VariablenNamen angegeben

if not bootimageVersion or (int(bootimageVersion) < 20111114):
    raise Exception(u"This product requires opsi-linux-bootimage version 20111114")
try:
    if not backend.isOpsi4():
        raise Exception
except:
    raise Exception(u"This is a opsi 4.0 product")

modifyPartitions = []
modifyPartitionTemplate = \
'''
<ModifyPartition wcm:action="add">
    <Active>%(active)s</Active>
    <Format>%(format)s</Format>
    <Label>%(label)s</Label>
    <Letter>%(letter)s</Letter>
    <Extend>false</Extend>
    <Order>%(order)s</Order>
    <PartitionID>%(partition)s</PartitionID>
</ModifyPartition>
'''

target = '/mnt/hd'
source = SCRIPT_PATH
srcDriversDir = source + '/drivers'
dstDriversDir = target + '/drv'
dstPeDriversDir = target + '/drvpe'
winpeNetworkMode = True

bootPartitionNumber = 0
bootPartitionSize   = productProperties.get('boot_partition_size', '0')
bootPartitionLabel  = productProperties.get('boot_partition_label', 'BOOT')
bootPartitionLetter = "S"
bootPartitionHidden = True
if (productProperties.get('boot_partition_letter', '-') != '-'):
    bootPartitionLetter = productProperties.get('boot_partition_letter')
    bootPartitionHidden = False

windowsPartitionNumber = 1
windowsPartitionSize   = productProperties.get('windows_partition_size','100%')
windowsPartitionLabel  =productProperties.get('windows_partition_label', 'WINDOWS')
windowsPartitionLetter = "C"

winpePartitionNumber = 2
winpePartitionSize   = "4000M"
winpePartitionLabel  = "WINPE"
winpePartitionLetter = "X"

#Hole dir die Eigenschaften der D:\ Partition
dataPartitionNumber = 0
datapartioncreate   = str(productProperties.get('data_partition_create', 'true')).lower()
dataPartitionSize   = productProperties.get('data_partition_size', 20480)
dataPartitionLabel  = productProperties.get('data_partition_label', 'DATA')
dataPartitionLetter = productProperties.get('data_partition_letter', 'D')

#Hole dir die Eigenschaften von E:\
#Idee: aktiviere die Spare-Partition nur, wenn!! diese als aktiviert angegeben ist
sparePartitionNumber = 0 
sparepartioncreate   = str(productProperties.get('spare_partition_create', 'true')).lower()
sparePartitionSize   = productProperties.get('spare_partition_size', '100%')
sparePartitionLabel  = productProperties.get('spare_partition_label', 'Spielwiese')
sparePartitionLetter = productProperties.get('spare_partition_letter', 'E')

blockAlignment = False
if (str(productProperties.get('blockAlignment', 'true')).lower() == 'true'):
    blockAlignment = True
   
if (str(productProperties.get('winpenetworkmode', 'true')).lower() == 'false'):
    winpeNetworkMode = False
#Abfrage eigentlich sinnlos, weil unsere Installation immer zwingend eine D:\ Partition vorraussetzt
if (windowsPartitionSize != "100%" and datapartioncreate == 'true'):
    dataPartitionNumber = 3
    if (sparepartioncreate == 'true'):
        sparePartitionNumber = 4

activePartition = "true"
if not bootPartitionSize.startswith("0"):
    bootPartitionNumber = 1
    windowsPartitionNumber += 1
    winpePartitionNumber += 1
    if (dataPartitionNumber > 0):
        dataPartitionNumber += 1
    if (sparePartitionNumber > 0):
        sparePartitionNumber += 1
    modifyPartitions.append(
		modifyPartitionTemplate % {
			"active":    activePartition,
			"format":    "NTFS",
			"label":     bootPartitionLabel,
			"letter":    bootPartitionLetter.upper(),
			"order":     len(modifyPartitions) + 1,
			"partition": bootPartitionNumber,
		}
	)
    activePartition = "false"

modifyPartitions.append(
    modifyPartitionTemplate % {
        "active":    activePartition,
        "format":    "NTFS",
        "label":     windowsPartitionLabel,
        "letter":    windowsPartitionLetter.upper(),
        "order":     len(modifyPartitions) + 1,
        "partition": windowsPartitionNumber,
    }
)

modifyPartitions.append(
    modifyPartitionTemplate % {
        "active":    "false",
        "format":    "",
        "label":     winpePartitionLabel,
        "letter":    winpePartitionLetter.upper(),
        "order":     len(modifyPartitions) + 1,
        "partition": winpePartitionNumber,
    }
)

if (dataPartitionNumber > 0):
    modifyPartitions.append(
        modifyPartitionTemplate % {
            "active":    "false",
            "format":    "NTFS",
            "label":     dataPartitionLabel,
            "letter":    dataPartitionLetter.upper(),
            "order":     len(modifyPartitions) + 1,
            "partition": dataPartitionNumber,
        }
    )
#lege hier genauso die Spare-Partition als Objekt an    
if (sparePartitionNumber > 0):
    modifyPartitions.append(
        modifyPartitionTemplate % {
            "active":    "false",
            "format":    "NTFS",
            "label":     sparePartitionLabel,
            "letter":    sparePartitionLetter.upper(),
            "order":     len(modifyPartitions) + 1,
            "partition": sparePartitionNumber,
        }
    )


pi = open(PATCHA_IN, 'a')
print >> pi, "windows_partition_number=%d" % windowsPartitionNumber
print >> pi, "winpe_partition_letter=%s" % winpePartitionLetter.upper()
print >> pi, "modify_partitions=%s" %''.join(modifyPartitions).replace('\n', '').replace('<Format></Format>', '')
pi.close()

# Do hardware inventory
logger.notice(u"Fetching opsi hw audit configuration")
hwconfig = backend.auditHardware_getConfig()

logger.notice(u"Running hardware inventory")
auditHardwareOnHosts = auditHardware(config = hwconfig, hostId = clientId)

logger.notice(u"Sending hardware information to service")
backend.auditHardwareOnHost_setObsolete(clientId)
backend.auditHardwareOnHost_updateObjects(auditHardwareOnHosts)

# Get harddisks
disks = getHarddisks()

# Use first Harddisk
disk = disks[0]
if blockAlignment:
    disk.setBlockAlignment(blockAlignment)
scriptMessageSubject.setMessage(u"Verwende Festplatte %s (%0.0f MB)." %(disk.device, (float(disk.size)/(1024*1024))))

# Check disk size
if (disk.size < 85000*1024*1024):
     #Disk smaller than 85000 MB => give up, Anpassung fuers IWW
     raise Exception(u"Die Festplatte ist zu klein")

# Get current partitions
partitions = disk.getPartitions()

if not partitions:
    # No partition found on harddisk
    scriptMessageSubject.setMessage(u"Keine Partitionen auf %s gefunden" % disk.device)
   
# Create new partitiontable
disk.deletePartitionTable()

# Partition table deleted => delete all netboot product states
backend.backend_setOptions( { 'addProductPropertyStateDefaults': False } )
deletePocs = []
for poc in backend.productOnClient_getObjects(clientId = clientId):
    if ((poc.productType == 'NetbootProduct') and (poc.productId !=productId)) or \
       ((poc.productType == 'LocalbootProduct') and(poc.installationStatus == 'not_installed') and (poc.actionRequest =='none')):
        deletePocs.append(poc)
backend.productOnClient_deleteObjects(deletePocs)

# Create partitions
diskSizeM = (float(disk.size)/(1024*1024)) #Angabe in MB
diskTotalSectors = disk.sectors
bootPartitionSizeM  = 0
dataPartitionSizeM  = 0
sparePartitionSizeM = 0

if not bootPartitionSize.startswith("0"):
    # Create boot partition
    if not blockAlignment:
        disk.createPartition(start = "0M", end = bootPartitionSize, fs ="ntfs")
        bootPartitionSizeM = int(bootPartitionSize.upper().replace('M','').replace('G', '').replace('B', ''))
        if (bootPartitionSize.upper().find('G') != -1):
            bootPartitionSizeM *= 1024
        logger.notice(u"Boot partition (%d) size is %dM" %(bootPartitionNumber, bootPartitionSizeM))
    else:
        disk.createPartition(start = "2048S", end = bootPartitionSize, fs = "ntfs")
        bootPartitionSizeM = int(bootPartitionSize.upper().replace('M','').replace('G', '').replace('B', ''))
        if (bootPartitionSize.upper().find('G') != -1):
            bootPartitionSizeM *= 1024
        logger.notice(u"Boot partition (%d) size is %dM" % (bootPartitionNumber, bootPartitionSizeM))
peStartM = int(diskSizeM - 4000)
boundaryM = int(diskSizeM)

if (windowsPartitionSize != "100%"):
    sizeM = 0
    if (windowsPartitionSize.find('%') != -1):
        percent = int(windowsPartitionSize.replace('%', ''))
        windowsPartitionSizeM =int((float(percent)/100.0)*float(diskSizeM-bootPartitionSizeM))
    else:
        windowsPartitionSizeM = int(windowsPartitionSize.upper().replace('M','').replace('G', '').replace('B', ''))
        if (windowsPartitionSize.upper().find('G') != -1):
            windowsPartitionSizeM *= 1024
    dataSizeM = diskSizeM - windowsPartitionSizeM
    logger.notice(u"Windows partiton (%s) size is %dM, data partition (%d) size is %dM" \
        % (windowsPartitionNumber, windowsPartitionSizeM, dataPartitionNumber, dataSizeM))
    if (dataSizeM <= 0):
        raise Exception(u"Not enough disk space for windows partiton size %dM" % windowsPartitionSizeM)
    boundaryM = bootPartitionSizeM + windowsPartitionSizeM
    peStartM = boundaryM - 4000

# Create windows partition
disk.createPartition(start = "%dM" % bootPartitionSizeM, end = "%dM" % peStartM, fs = "ntfs")

# Create winpe partition
disk.createPartition(start = "%dM" % peStartM, end = "%dM" % boundaryM, fs = "fat32", boot = True)

if (dataPartitionNumber > 0):
        #Berechne als erstes die Groesse der D:\ Partition in ganzen MB
        if (dataPartitionSize.find('%') != -1):
            percent = int(dataPartitionSize.replace('%', ''))
            dataPartitionSizeM =int((float(percent)/100.0)*float(diskSizeM-bootPartitionSizeM-windowsPartitionSizeM))
        else:
            dataPartitionSizeM = int(dataPartitionSize.upper().replace('M','').replace('G', '').replace('B', ''))
            if (dataPartitionSize.upper().find('G') != -1):
                dataPartitionSizeM *= 1024        
        #sollte ausreichend  Platz auf der Platte sein, um die volle 20GB Partition anzulegen
        if ((boundaryM + dataPartitionSizeM) <= diskSizeM):
            # Create data partition
            disk.createPartition(start = "%dM" % boundaryM, end = "%dM" % (boundaryM + dataPartitionSizeM), fs = "ntfs")
            #wenn noch Platz ist, verschiebe jetzt die BoundaryM um die Groesse der Datenpartition
            boundaryM += dataPartitionSizeM
        #Falls ueberhaupt kein Platz mehr auf der platte sein sollte, so schreibe das in log, werfe eine Exception und deaktivere die E:\ Partition
        elif(boundaryM >= diskSizeM):
            logger.notice(u"Es steht auf der ersten Platte nicht genug Speicher fuer D:\ zur Verfuegung")
            raise Exception(u"Problem, absolut kein Platz mehr fuer D:\ auf der Platte")
            sparePartitionNumber = 0
        #ansonsten lege die max. moegliche grosse Partition D:\ an
        else:
             disk.createPartition(start = "%dM" % boundaryM, end = "%dM" % diskSizeM, fs = "ntfs")   
             #Deaktivere die sparePartition E: 
             sparePartitionNumber = 0    

#lege jetzt die SparePartition an, aber nur, wenn vorher D:\ in voller Groesse angelegt werden konnte             
if (sparePartitionNumber > 0):
        #Berechne als erstes die Groesse der E:\ Partition in ganzen MB
        if (sparePartitionSize.find('%') != -1):
            percent = int(sparePartitionSize.replace('%', ''))
            sparePartitionSizeM =int((float(percent)/100.0)*float(diskSizeM-bootPartitionSizeM-windowsPartitionSizeM-dataPartitionSizeM))
        else:
            sparePartitionSizeM = int(sparePartitionSize.upper().replace('M','').replace('G', '').replace('B', ''))
            if (sparePartitionSize.upper().find('G') != -1):
                sparePartitionSizeM *= 1024        
        #sollte ausreichend  Platz auf der Platte sein, um die volle 20GB Partition anzulegen
        if ((boundaryM + sparePartitionSizeM) <= diskSizeM):
            # Create data partition
            disk.createPartition(start = "%dM" % boundaryM, end = "%dM" % (boundaryM + sparePartitionSizeM), fs = "ntfs")
        #Falls ueberhaupt kein Platz mehr auf der platte sein sollte, so schreibe das in log, lege kein E:\ an
        elif(boundaryM >= diskSizeM):
            logger.notice(u"Es steht auf der ersten Platte nicht genug Speicher fuer E:\ zur Verfuegung")
            sparePartitionNumber = 0
        #ansonsten lege die max. moegliche grosse Partition E:\ an
        else:
             disk.createPartition(start = "%dM" % boundaryM, end = "%dM" % diskSizeM, fs = "ntfs")   
            
partitions = disk.getPartitions()


# Create fat32 filesystem on winpe partition
disk.createFilesystem(partition = winpePartitionNumber, fs = "fat32")

if (dataPartitionNumber > 0):
    # Create ntfs filesystem on data partition
    disk.createFilesystem(partition = dataPartitionNumber, fs = "ntfs")
    
if (sparePartitionNumber > 0):
    # Create ntfs filesystem on spare partition
    disk.createFilesystem(partition = sparePartitionNumber, fs = "ntfs")

# Write Master Boot Record
disk.writeMasterBootRecord(system = 'vista')

# Write Partition Boot Record
disk.writePartitionBootRecord(partition = winpePartitionNumber, fsType ='fat32nt60')

# Mount partition
disk.mountPartition(partition = winpePartitionNumber, mountpoint = target)

# Copy PE files
depot.copy(source + '/winpe/*', target)
if not os.path.exists(os.path.join(target, 'bootmgr')):
    raise Exception("bootmgr not found in winpe, please check winpe folder on server")

# Copy Windows installation files
if not winpeNetworkMode:
    depot.copy(source + '/installfiles', target)

# Copy opsi files
depot.copy(source + '/opsi', target + '/')

# Copy opsi-client-agent
depot.copy('/opsi-client-agent', target + '/opsi/')
copy(target + '/opsi/opsi-client-agent/files/opsi/postinst.d/*', target + '/opsi/postinst.d/')

# Copy custom files
depot.copy(source + '/custom/unattend.xml', target + '/opsi/')
depot.copy(source + '/custom/postinst.d/*', target + '/opsi/postinst.d/')

# Copy sysconf.ini to opsi-client-agent config dir
copy(SYSCONF_INI , target + '/opsi/opsi-client-agent/files/opsi/cfg')

# Integrate drivers
os.makedirs(dstDriversDir)
os.makedirs(dstPeDriversDir)
if depot.exists(srcDriversDir):
    scriptMessageSubject.setMessage("Treiber-Verzeichnis '%s' gefunden, starte Treiberintegration" % srcDriversDir)
    additionalDrivers = [ ad.strip() for ad in(u','.join(productPropertyValues.get('additional_drivers',[u'']))).split(u',') ]
    integrateAdditionalWindowsDrivers(srcDriversDir + u'/drivers/additional', dstDriversDir, additionalDrivers, messageSubject = scriptMessageSubject, srcRepository = depot, auditHardwareOnHosts = auditHardwareOnHosts)
    integrateWindowsHardwareDrivers(srcDriversDir, dstDriversDir, auditHardwareOnHosts, messageSubject = scriptMessageSubject, srcRepository = depot)

# Create work.cmd
logger.notice("Creating work.cmd")
f = open(target + '/opsi/work.cmd', 'w')
print >> f, "@echo off\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"

if winpeNetworkMode and (depot._url.startswith('smb:') or depot._url.startswith('cifs:')):
    match = re.search('^smb://([^/]+)/([^/]+)(.*)$', depot._url, re.IGNORECASE)
    if not match:
        raise Exception("Bad depot-URL '%s'" % depot._url)
    hn = match.group(1)
    sn = match.group(2)
    pn = match.group(3)
   
    print >> f, "goto mountshare\r"
    print >> f, ":drvloadnetwork\r"
    if os.path.exists(dstDriversDir):
        storageControllerInfo = disk.getControllerInfo()
        for filePath in findFiles(prefix = dstDriversDir, directory = dstDriversDir, includeFile = re.compile('\.inf$', re.IGNORECASE), returnDirs = False):
            infFile = InfFile(filePath)
            if infFile.isDeviceKnown(usedNetworkDevice['vendorId'], usedNetworkDevice['deviceId']):
                logger.info(u"Integrating winpe driver for network controller: %s" % usedNetworkDevice)
                filePath = filePath[len(target):]
                if filePath.startswith('/'):
                    filePath = filePath[1:]
                filePath = 'c:\\' + filePath.replace('/', '\\')
                logger.notice("Adding to work.cmd: drvload %s\r" % filePath )
                print >> f, "drvload %s\r" % 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)
   
    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"
f.close()

# Create startnet.cmd
logger.notice(u"Creating startnet.cmd")
f = open(target + '/opsi/startnet.cmd', 'w')
print >> f, "@echo off\r"
print >> f, "copy c:\\opsi\\work.cmd x:\\work.cmd >nul\r"
print >> f, "x:\\work.cmd"
f.close()

# Create diskpart.txt
logger.notice(u"Creating diskpart.txt")
f = open(target + '/opsi/diskpart.txt', 'w')
f = open(target + '/opsi/diskpart.txt', 'w')
print >> f, "list disk\r"
print >> f, "select disk 0\r"
print >> f, "list partition\r"
print >> f, "list volume\r"
print >> f, "select partition %d\r" % winpePartitionNumber
print >> f, "delete partition noerr override\r"
print >> f, "select partition %d\r" % (winpePartitionNumber - 1)
print >> f, "extend\r"
if bootPartitionNumber and bootPartitionHidden:
    print >> f, "select volume %s\r" % bootPartitionLetter
    print >> f, "remove letter=%s\r" % bootPartitionLetter
print >> f, "exit\r"
f.close()

# Patch files
logger.notice(u"Patching unattend.xml and config.ini")
for i in ( target + '/opsi/unattend.xml', target + '/opsi/opsi-client-agent/files/opsi/cfg/config.ini' ):
    execute('/usr/local/bin/patcha %s' % i)
    execute('/usr/local/bin/patcha -f %s %s' % (PATCHA_IN, i))

# Debug output of file content
for fn in ('/opsi/work.cmd', '/opsi/startnet.cmd', '/opsi/diskpart.txt'):
    execute("%s '%s'" % (which('cat'), target + fn))

# Umount partition
disk.umountPartition(partition = winpePartitionNumber)

# Reboot
reboot()
Antworten