From 4e3359fd68c7e15563038974975913f09917dced Mon Sep 17 00:00:00 2001 From: Mike Hiretsky Date: Fri, 3 Sep 2010 14:48:21 +0400 Subject: [PATCH] Rewrite setDiskOptions. Fix crash with wrong fstab file. --- pym/cl_fill_install.py | 31 ++- pym/cl_install.py | 428 +++++++++++++++++------------------------ 2 files changed, 196 insertions(+), 263 deletions(-) diff --git a/pym/cl_fill_install.py b/pym/cl_fill_install.py index acb9e77..6c831ec 100644 --- a/pym/cl_fill_install.py +++ b/pym/cl_fill_install.py @@ -189,11 +189,24 @@ class fillVars(object, glob_attr): if key in blkid_hash: key = blkid_hash[key] disk_hash[dev][key] = value[1:-1] - mountOptionsList = filter(lambda x: x[0] in disk_hash.keys(), - map(lambda y: (y[0],filter(lambda z: z!="rw", y[3].split(','))), - map(lambda x: filter(lambda x: x ,x.replace('\t',' ').split(' ')), + # discard comment and empty string + mountOptionsList = \ filter(lambda x: x.strip() and not x.strip().startswith('#'), - open("/etc/fstab").readlines())))) + open("/etc/fstab").readlines()) + # split all string by columns and discard string which has less that 4 + # columns + mountOptionsList = \ + filter(lambda x: len(x)>=4, + map(lambda x: filter(lambda x: x , + x.replace('\t',' ').split(' ')), + mountOptionsList)) + # split options and discard rw opt + mountOptionsList = \ + filter(lambda x: x[0] in disk_hash.keys(), + map(lambda y: (y[0],filter(lambda z: z!="rw", + y[3].split(','))), + mountOptionsList)) + dictOptionList = {} dictOptionList.update(mountOptionsList) for dev in disk_hash.keys(): @@ -254,10 +267,11 @@ class fillVars(object, glob_attr): # convert fstab to # [['/dev/sda3', '/', '', 'reiserfs', 'noatime', '', '', '0', '2\n'], # ['/dev/sda5', '/var/calculate', 'reiserfs', 'noatime', '0', '0\n']] - listFstab = map(lambda x: filter(lambda x: x, + listFstab = filter(lambda x: len(x) >= 4, + map(lambda x: filter(lambda x: x, x.replace('\t',' ').split(' ')), filter(lambda x: not x.startswith('#') and x.strip(), - open("/etc/fstab"))) + open("/etc/fstab")))) # get mount point or device or dir return filter(lambda x: x!=absPath, reduce(lambda x,y: y, @@ -563,10 +577,11 @@ class fillVars(object, glob_attr): # convert fstab to # [['/dev/sda3', '/', '', 'reiserfs', 'noatime', '', '', '0', '2\n'], # ['/dev/sda5', '/var/calculate', 'reiserfs', 'noatime', '0', '0\n']] - listFstab = map(lambda x: filter(lambda x: x, + listFstab = filter(lambda x: len(x)>=4, + map(lambda x: filter(lambda x: x, x.replace('\t',' ').split(' ')), filter(lambda x: not x.startswith('#') and x.strip(), - open("/etc/fstab"))) + open("/etc/fstab")))) return dict(map(lambda x:[x[0],x[1]], filter(lambda x: "bind" in x[3], listFstab))) diff --git a/pym/cl_install.py b/pym/cl_install.py index 001f494..4218bbc 100644 --- a/pym/cl_install.py +++ b/pym/cl_install.py @@ -746,29 +746,6 @@ class cl_install(color_print): else: return dirsFiles - def _getTransferedDisksAndSwap(self,skipDev): - """Get swap and disk info from fstab""" - def seporator(lists,disk): - """If mountPoint of disk contains swap, then - append it to second list else in firest""" - if disk['mountPoint'] == 'swap': - return (lists[0],lists[1]+[disk]) - else: - return (lists[0]+[disk],lists[1]) - return reduce(seporator, - map(lambda x:{'isFormat':False, - 'dev':x[0], - 'options':x[1].split(','), - 'mountPoint':x[2], - 'fileSystem':x[3]}, - filter(lambda x: not x[2] in ('','/') and - not x[0] in skipDev, - zip(self.clVars.Get('os_disk_dev'), - self.clVars.Get('os_disk_options'), - self.clVars.Get('os_install_disk_mount'), - self.clVars.Get('os_disk_format')))), - ([],[])) - def _getTransferedBind(self,skipSrc,skipDest): def list2binddict(l): return {'srcMountPoint':l[0], @@ -810,258 +787,199 @@ class cl_install(color_print): self.printWARNING(_("See 'man mount' for file system") + " "+\ ", ".join(convObj.listFileSystemCorrupted)) return False - # get current fstab config - fstabDisks,fstabSwap = self._getTransferedDisksAndSwap( - map(lambda x: x['dev'],listDisks+listSwaps)) - fstabBinds = self._getTransferedBind( - map(lambda x: x['srcMountPoint'],listBinds), - map(lambda x: x['destMountPoint'],listBinds)) - self.listDisksOptions = sorted( fstabDisks + listDisks, - lambda x,y:cmp(x['mountPoint'],y['mountPoint'])) - #self.listBindsOptions = sorted( fstabBinds + listBinds, - # lambda x,y:cmp(x['destMountPoint'], - # y['destMountPoint'])) - self.listBindsOptions = fstabBinds + listBinds - self.listSwapsOptions = listSwaps or fstabSwap - installAllDevices = map(lambda x: x['dev'],listSwaps) +\ - map(lambda x: x['dev'],listDisks) - # detect duplicate partition - dupDevices = filter(lambda x: installAllDevices.count(x)>1, - set(installAllDevices)) - if dupDevices: - self.printERROR(_("Duplicate devices %s")%", ".join(dupDevices)) + usedDevicesOnlyDisks = map(lambda x:x['dev'],listDisks) + usedDevicesOnlySwap = map(lambda x:x['dev'],listSwaps) + usedDevices = map(lambda x:x['dev'],listSwaps)+usedDevicesOnlyDisks + usedMP = map(lambda x:x['mountPoint'],listDisks) + \ + map(lambda x:x['destMountPoint'],listBinds) + # check specified devices + wrongDevices = list(set(usedDevicesOnlyDisks) - \ + set(self.clVars.Get('os_disk_dev'))) + wrongDevices = list(set(usedDevicesOnlySwap) - \ + set(self.clVars.Get('os_disk_dev')+["none"])) + if wrongDevices: + self.printERROR(_("Incorrect device '%s'")%wrongDevices[0]) return False + # detect using extended partition extendedPartitions = map(lambda x: x[1], filter(lambda x: x[0]=="extended", zip(self.clVars.Get('os_disk_part'), self.clVars.Get('os_disk_dev')))) - for dev in installAllDevices: - flagError = False - if dev in extendedPartitions: - flagError = True - self.printERROR(_("Can not use extended partition %s")%dev) - if flagError: - return False - if installAllDevices: - listDevAndMount = zip(self.clVars.Get('os_disk_dev'), - self.clVars.Get('os_disk_mount')) - currentSwapDevices = map(lambda y: y[0], - filter(lambda x: x[1]=="swap", - listDevAndMount)) - newSwapDevices = map(lambda x: x['dev'], listSwaps) - equalSwapDevices = set(currentSwapDevices)&set(newSwapDevices) - isFormattedSwapDevices = list(set(newSwapDevices)-\ - set(equalSwapDevices)) - # list of devices that will be formatted - isFormattedDevices = isFormattedSwapDevices +\ - map(lambda x: x['dev'], - filter(lambda x: x['isFormat'], - listDisks)) - # find devices on loaded system and check mounted - listMount = filter(lambda x:\ - x[0] in isFormattedDevices and x[1]!='', - listDevAndMount) - if listMount: - for dev, mountPoint in listMount: - self.printERROR(_("Specified disk '%s' mounted to")\ - %dev + " " + _("'%s' in current system")\ - %mountPoint) - return False - osDiskDevices = self.clVars.Get('os_disk_dev') - if listDisks: - cmdDevices = map(lambda x: x['dev'], listDisks) - cmdMountPoints = map(lambda x: x['mountPoint'], listDisks) - - # check for other partition not use current root device - rootdev = self.clVars.Get('os_root_dev') - if filter(lambda x: x == rootdev,cmdDevices): - self.printERROR( - _("Specified disk '%s' mounted to '/' in current system") % - rootdev) - return False - # Check '/' in start path - wrongCmdMountPoints = filter(lambda x: not x[0]=="/" and x!="none", - cmdMountPoints) - if wrongCmdMountPoints: - for wrongMointPoint in wrongCmdMountPoints: - self.printERROR(_("Wrong moint point '%s'")%wrongMointPoint) - return False - # Check '/' in start device - wrongCmdDevices = filter(lambda x: not x[0]=="/", cmdDevices) - if wrongCmdDevices: - for wrongDevice in wrongCmdDevices: - self.printERROR(_("Wrong device '%s'")%wrongDevice) - return False - # find wrong disks - wrongDisks = filter(lambda x: not x in osDiskDevices, - cmdDevices) - if wrongDisks: - self.printERROR(_("Device %s is not exists"\ - %", ".join(wrongDisks))) - return False + usingExtPart = list(set(usedDevices)&set(extendedPartitions)) + if usingExtPart: + self.printERROR(_("Can not use extended partition %s")% + usingExtPart[0]) + return False - # root partition needed - listRootDict = filter(lambda x: x['mountPoint'] == '/', listDisks) - if not listRootDict: - self.printERROR(_("Need specify root partition")) - return False + srcMountPoints = map(lambda x:x['srcMountPoint'],listBinds) + destMountPoints = map(lambda x:x['destMountPoint'],listBinds) + wrongBind = filter(lambda x:x in destMountPoints,srcMountPoints) + if wrongBind: + incompBind = filter(lambda x:x[1]==wrongBind[0], + zip(srcMountPoints,destMountPoints)) + self.printERROR( + _("Source directory %s already use for bind '%s' to '%s'")% + (wrongBind[0],incompBind[0][0],incompBind[0][1])) + return False + # Check bind params + wrongBind = filter(lambda x:not x[0].startswith("/") or + not x[1].startswith("/") and + x[1] != "none", + zip(srcMountPoints,destMountPoints)) + if wrongBind: + self.printERROR(_("Incorrect moint point (bind '%s' to '%s')")% + (wrongBind[0][0],wrongBind[0][1])) + return False - # detect duplicate mountPoints - dupPoint = filter(lambda x: x != "none" and - cmdMountPoints.count(x)>1, - set(cmdMountPoints)) - if dupPoint: - self.printERROR(_("Duplicate mount points %s")\ - %", ".join(dupPoint)) - return False + # Check '/' in start path + wrongMP = filter(lambda x: not x.startswith("/") and x!="none", + usedMP) + \ + filter(lambda x: not x.startswith("/"), + map(lambda x:x['srcMountPoint'],listBinds)) + if wrongMP: + self.printERROR(_("Incorrect moint point '%s'")%wrongMP[0]) + return False + + # detect duplicate devices + dupDevices = list(set(filter(lambda x:usedDevices.count(x)>1, + usedDevices))) + if dupDevices: + self.printERROR(_("Device '%s' is used twice")%dupDevices[0]) + return False + # detect duplicate mount points + dupMP = list(set(filter(lambda x:usedMP.count(x)>1, + usedMP))) + if dupMP: + self.printERROR(_("Mount point '%s' is used twice")%dupMP[0]) + return False - rootDev = listRootDict[0]['dev'] - # find device on loaded system and check mounted - loadMount = filter(lambda x:x[0] == rootDev and x[1] != '', + clearSwap = lambda data,isswap: data if len(listSwaps) == 0 or \ + isswap != "swap" else "" + # get hash from current variables + devMount = dict(map(lambda x:(x[0], + {'mountPoint':clearSwap(x[1],x[1]), + 'fileSystem':x[2], + 'options':clearSwap(x[3],x[1]), + 'isFormat':""}), zip(self.clVars.Get('os_disk_dev'), - self.clVars.Get('os_disk_mount'))) - if loadMount: - self.printERROR( - _("Specified root disk '%s' mounted to") %rootDev+ " " +\ - _(" '%s' in current system") %loadMount[0][1]) - return False - # set template variables - self.clVars.Set('os_install_root_dev',rootDev,True) - - # change os_install_disk_mount - for disk in listDisks: - if disk['mountPoint'] == "none": - disk['mountPoint'] = "" - newDisks = dict(map(lambda x: (x['dev'],x['mountPoint']),listDisks)) - listInstallDiskMount = map(lambda x:\ - newDisks[x[0]] if x[0] in newDisks else x[1], - zip(self.clVars.Get('os_disk_dev'), - self.clVars.Get('os_install_disk_mount'))) - self.clVars.Set('os_install_disk_mount',listInstallDiskMount,True) - - listInstallMountOptions = [] - listInstallFileSystem = [] - listInstallPerformFormat = [] - for dev, oldFileSystem, mountPoint, oldMountOpt in zip(\ - self.clVars.Get('os_disk_dev'), - self.clVars.Get('os_disk_format'), - self.clVars.Get('os_install_disk_mount'), - self.clVars.Get('os_disk_options')): - cmdDataDev = filter(lambda x: x["dev"]==dev, listDisks) - cmdMountOptions = "" - if mountPoint: - if cmdDataDev: - cmdMountOptions = cmdDataDev[0]["options"] - newFileSystem = cmdDataDev[0]["fileSystem"] - isFormat = "yes" if cmdDataDev[0]["isFormat"] else "" - else: - newFileSystem = oldFileSystem - isFormat = "" - listInstallFileSystem.append(newFileSystem) - if cmdMountOptions: - mountOptions = ",".join(cmdMountOptions) - elif oldMountOpt and\ - oldFileSystem==newFileSystem: - mountOptions = oldMountOpt - else: - mountOptions = "noatime" - listInstallMountOptions.append(mountOptions) - listInstallPerformFormat.append(isFormat) - else: - listInstallMountOptions.append("") - listInstallFileSystem.append(oldFileSystem) - listInstallPerformFormat.append("") - self.clVars.Set('os_install_disk_options', listInstallMountOptions, - True) - self.clVars.Set('os_install_disk_format', listInstallFileSystem, - True) - self.clVars.Set('os_install_disk_perform_format', - listInstallPerformFormat, True) - - if listBinds: - cmdBindSrcDirs = map(lambda x: x['srcMountPoint'], listBinds) - cmdBindDestDirs = map(lambda x: x['destMountPoint'], listBinds) - # Check '/' in start path - flagWrongBindPath = False - for srcDir, destDir in zip(cmdBindSrcDirs, - cmdBindDestDirs): - if not (srcDir[0]=="/" and \ - (destDir[0]=="/" or destDir == "none")): - self.printERROR(\ - _("Incorrect mount point (bind '%s' to '%s')") - %(srcDir, destDir)) - flagWrongBindPath = True - if flagWrongBindPath: - return False - # remove from old the mountpoint - loadbinds = filter(lambda x:not x[0] in cmdBindSrcDirs and - not x[1] in cmdBindDestDirs, - zip(self.clVars.Get('os_install_bind_dir'), - self.clVars.Get('os_install_bind_mountpoint'))) - # add new to old - loadbinds = loadbinds + filter(lambda x:x[1] != "none", - zip(cmdBindSrcDirs,cmdBindDestDirs)) - # set template variables - # reset new bind dirs - self.clVars.Set('os_install_bind_dir', - map(lambda x:x[0],loadbinds),True) - self.clVars.Set('os_install_bind_mountpoint', - map(lambda x:x[1],loadbinds),True) - if listSwaps: - listInstallMountPoint = [] - listInstallMountOptions = [] - listInstallFileSystem = [] - # Check '/' in start device - wrongDevices = filter(lambda x: not x["dev"] in osDiskDevices and \ - x["dev"]!="none", - listSwaps) - if wrongDevices: - for wrongDev in wrongDevices: - self.printERROR(_("Incorrect device '%s'")%wrongDev["dev"]) + self.clVars.Get('os_install_disk_mount'), + self.clVars.Get('os_install_disk_format'), + self.clVars.Get('os_install_disk_options')))) + dictMountDev = dict(zip(self.clVars.Get('os_install_disk_mount'), + self.clVars.Get('os_disk_dev'))) + # update current variable by cmd params + for diskData in listDisks+listSwaps: + dev = diskData['dev'] + # skip none swap device + if dev == "none": + continue + mountPoint = diskData.get('mountPoint','swap') + isFormat = diskData['isFormat'] + if mountPoint == "none": + mountPoint = "" + curMP = devMount[dev]['mountPoint'] + if curMP and ( curMP != mountPoint and isFormat or curMP == '/' ): + self.printERROR(_("Specified disk '%s' mounted to")\ + %dev + " " + _("'%s' in current system")\ + %curMP) return False - for dev, mountPoint, fileSystem, mountOpt in zip(\ - self.clVars.Get('os_disk_dev'), - self.clVars.Get('os_install_disk_mount'), - self.clVars.Get('os_install_disk_format'), - self.clVars.Get('os_install_disk_options')): - - if filter(lambda x: x["dev"]==dev, listSwaps): - listInstallMountPoint.append("swap") - listInstallMountOptions.append("sw") - listInstallFileSystem.append("swap") - else: - if mountPoint == "swap": - listInstallMountPoint.append("") - listInstallMountOptions.append("") - listInstallFileSystem.append("") - else: - listInstallMountPoint.append(mountPoint) - listInstallMountOptions.append(mountOpt) - listInstallFileSystem.append(fileSystem) - self.clVars.Set('os_install_disk_mount', listInstallMountPoint, - True) - self.clVars.Set('os_install_disk_options', listInstallMountOptions, - True) - self.clVars.Set('os_install_disk_format', listInstallFileSystem, - True) + else: + if mountPoint in dictMountDev and mountPoint != "swap": + devMount[dictMountDev[mountPoint]]['mountPoint'] = '' + devMount[dev]['mountPoint'] = mountPoint + devMount[dev]['options'] = ",".join(diskData['options']) + devMount[dev]['fileSystem'] = diskData['fileSystem'] + if isFormat: + devMount[dev]['isFormat'] = "yes" + + bindDestSrc = dict(zip(self.clVars.Get('os_install_bind_mountpoint'), + self.clVars.Get('os_install_bind_dir'))) + bindSrcDest = dict(zip(self.clVars.Get('os_install_bind_dir'), + self.clVars.Get('os_install_bind_mountpoint'))) + + for bindData in listBinds: + srcMountPoint = bindData['srcMountPoint'] + destMountPoint = bindData['destMountPoint'] + if destMountPoint in dictMountDev: + devMount[dictMountDev[destMountPoint]]['mountPoint'] = '' + if destMountPoint == "none" and srcMountPoint in bindSrcDest and \ + bindSrcDest[srcMountPoint] in bindDestSrc: + bindDestSrc.pop(bindSrcDest[srcMountPoint]) + bindSrcDest.pop(srcMountPoint) + else: + bindDestSrc[destMountPoint] = srcMountPoint + if destMountPoint in bindSrcDest: + bindDestSrc.pop(bindSrcDest[destMountPoint]) + bindSrcDest[srcMountPoint] = destMountPoint + + # update bind variables by new hash + new_bind_dest, new_bind_src = \ + reduce(lambda x,y:[x[0]+[y[0]],x[1]+[y[1]]], + sorted(bindDestSrc.items()),[[]]*2) + # update variables by new hash + new_mount, new_format, new_isformat, new_options= \ + reduce(lambda x,y:[x[0]+[devMount[y]['mountPoint']], + x[1]+[devMount[y]['fileSystem']], + x[2]+[devMount[y]['isFormat']], + x[3]+[devMount[y]['options']]], + sorted(devMount.keys()),[[]]*4) + + map(lambda x:self.clVars.Set(x[0],x[1],True), + (('os_install_disk_mount',new_mount), + ('os_install_disk_mount',new_mount), + ('os_install_disk_format',new_format), + ('os_install_disk_perform_format',new_isformat), + ('os_install_disk_options',new_options), + ('os_install_bind_dir',new_bind_src), + ('os_install_bind_mountpoint',new_bind_dest))) + + rootDev = self.getFieldByField("dev","mount","/", + secondPrefix="os_install_disk") + if not rootDev: + self.printERROR(_("Need specify root partition")) + return False + self.clVars.Set('os_install_root_dev',rootDev,True) + + # update listDisksOptions, listSwapsOptions and listBindOptions + diskData = zip(self.clVars.Get('os_disk_dev'), + self.clVars.Get('os_install_disk_mount'), + self.clVars.Get('os_install_disk_format'), + self.clVars.Get('os_install_disk_options'), + self.clVars.Get('os_install_disk_perform_format')) + bindData = zip(self.clVars.Get('os_install_bind_dir'), + self.clVars.Get('os_install_bind_mountpoint')) + listToOptDict = lambda x: {'dev':x[0], + 'mountPoint':x[1], + 'fileSystem':x[2], + 'options':x[3].split(','), + 'isFormat':True if x[4] == "yes" else False} + listToOptDictBind = lambda x:{'srcMountPoint':x[0], + 'destMountPoint':x[1], + 'options':['bind'], + 'isFormat':False, + 'fileSystem':'none'} + self.listDisksOptions = map(listToOptDict, + filter(lambda x:x[1] and x[1] != "swap", + diskData)) + self.listSwapsOptions = map(listToOptDict, + filter(lambda x: x[1] == "swap", + diskData)) + + self.listBindsOptions = map(listToOptDictBind,bindData) + + osDiskDevices = self.clVars.Get('os_disk_dev') + updateIdDict = dict(map(lambda x:(x[0],x[2]),filter(lambda x:x[1]!=x[2], zip(self.clVars.Get('os_disk_dev'), self.clVars.Get('os_disk_id'), self.clVars.Get('os_install_disk_id'))))) - - # discard disks without mountPoint (it specified with none mountPoint) - self.listDisksOptions = filter(lambda x: x['mountPoint'], - self.listDisksOptions) - self.listSwapsOptions = filter(lambda x: x['dev'] != "none", - self.listSwapsOptions) - self.listBindsOptions = filter(lambda x: x['destMountPoint'] != "none", - self.listBindsOptions) for disk in self.listDisksOptions + self.listSwapsOptions: if disk['dev'] in updateIdDict: disk['systemId'] = updateIdDict[disk['dev']] else: disk['systemId'] = None + # use or not MBR bootDiskGrub = "" if mbrDisk == "off": self.clVars.Set('os_install_mbr',"",force=True)