#-*- coding: utf-8 -*- # Copyright 2010 Mir Calculate Ltd. http://www.calculate-linux.org # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __version__ = "2.2.0.0" __app__ = "calculate-install" import os import re import sys import traceback from os.path import exists as pathexists import cl_overriding install_errors = "" def installExit(*args,**kwars): raise InstallError(globals()["install_errors"]) def overprintERROR(s): globals()["install_errors"] += str(s) +"\n" def get_install_errors(): return globals()["install_errors"] cl_overriding.exit = installExit cl_overriding.printERROR = overprintERROR from cl_lang import lang from cl_fill import clLocale from cl_template import template from cl_datavars import DataVars from cl_print import color_print from cl_distr import PartitionDistributive,DistributiveRepository,\ DistributiveError, ScratchDistributive, MultiPartitions from cl_string import tableReport from time import sleep from subprocess import Popen,PIPE from server.utils import dialogYesNo from cl_migrate_users import migrate from cl_utils import getUserPassword from encrypt import encrypt tr = lang() tr.setGlobalDomain('cl_install') tr.setLanguage(sys.modules[__name__]) class InstallError(Exception): """Installation Error""" pass class printNoColor: def colorPrint(self,attr,fg,bg,string): sys.stdout.write(string) class DataVarsInstall(DataVars): """Variable class for installation""" def importInstall(self, **args): '''Заполнить конфигурацию переменных, для десктопа''' # Имя секции в calculate.env envSection = "calculate-install" # заполнить переменные окружения алгоритмом по умолнанию self.importData(envSection, ('cl_vars_install','cl_fill_install')) class convertDictOpt: """Convert dict install option""" _defaultFS = "reiserfs" _diskDefaultMountPoints = { "default":{"fileSystem":_defaultFS, "isFormat":False, "options":["noatime"]}, "/":{"fileSystem":_defaultFS, "isFormat":True, "options":["noatime"]}, "none":{"fileSystem":"", "isFormat":False, "options":[""]},} #"/boot":{"fileSystem":"ext2", # "isFormat":True, # "options":["noatime"]}} _bindDefaultMountPoint = {"fileSystem":"none", "isFormat":False, "options":["bind"]} _swapDefaultMountPoint = {"fileSystem":"swap", "isFormat":False, "options":["sw"]} _propertiesFileSystem = {"default": {"fileSystem":_defaultFS, "isFormat":True, "options":[]}, "noformat":{"fileSystem":"", "isFormat":False, "options":[]}} _ext2Options = {"options":["acl", "noacl", "bsddf", "minixdf", "check", "debug", "errors", "grpid", "bsdgroups", "nogrpid", "sysvgroups", "grpquota", "noquota", "quota", "usrquota","nobh", "nouid32", "oldalloc", "orlov", "resgid","resuid", "sb", "user_xattr", "nouser_xattr"], "pair":{"check":{"options":["none", "nocheck"], "incompatible":["none", "nocheck"]}, "errors":{"options":["continue", "remount-ro", "panic"], "incompatible":["continue","remount-ro", "panic"]}, "resgid":{"options":re.compile("\d+"), "incompatible":[]}, "resuid":{"options":re.compile("\d+"), "incompatible":[]}, "sb":{"options":re.compile("\d+"), "incompatible":[]}}, "incompatible":[["acl","noacl"], ["bsddf", "minixdf"], ["grpid","bsdgroups"], ["grpid","nogrpid"], ["bsdgroups","sysvgroups"], ["nogrpid","sysvgroups"], ["grpquota","noquota","quota", "usrquota"], ["oldalloc","orlov"], ["user_xattr","nouser_xattr"]]} _ext3Options = _ext2Options.copy() _ext3Options["options"] += ["journal", "noload", "data", "barrier", "commit", "data_err"] _ext3Options["pair"].update({"journal":{"options":["update", "inum"], "incompatible":["update", "inum"]}, "data":{"options":["journal", "ordered", "writeback"], "incompatible":["journal", "ordered", "writeback"]}, "data_err":{"options":["abort", "ordered", "ignore"], "incompatible":["abort", "ordered", "ignore"]}, "barrier":{"options":["0","1"], "incompatible":["0","1"]}, "commit":{"options":re.compile("\d+"), "incompatible":[]}}) _fileSystemOpt = {"_all":{"options":["async", "atime", "noatime", "auto", "noauto", "defaults", "dev", "nodev", "diratime", "nodiratime", "dirsync", "exec", "noexec", "group", "iversion", "noiversion", "mand", "nomand", "_netdev", "nofail", "relatime", "norelatime", "strictatime", "nostrictatime", "suid", "nosuid", "owner", "remount", "ro", "rw", "sync", "user", "nouser", "users"], "pair": {}, "incompatible":[["sync", "async"], ["atime", "noatime"], ["auto", "noauto"], ["dev", "nodev"], ["diratime", "nodiratime"], ["exec", "noexec"], ["iversion", "noiversion"], ["mand", "nomand"], ["relatime", "norelatime"], ["strictatime", "nostrictatime"], ["suid", "nosuid"], ["ro", "rw"], ["user", "nouser"]]}, "ext2":_ext2Options, "ext3":_ext3Options, "ext4":{"options":["journal_dev", "noload", "data", "commit", "orlov", "oldalloc", "user_xattr", "nouser_xattr", "acl", "noacl", "bsddf", "minixdf", "debug", "errors", "data_err", "grpid", "bsdgroups", "nogrpid", "sysvgroups", "resgid", "resuid", "sb", "quota", "noquota", "grpquota", "usrquota", "bh", "nobh", "journal_checksum", "journal_async_commit", "journal", "barrier", "nobarrier", "inode_readahead", "stripe", "delalloc", "nodelalloc", "max_batch_time", "journal_ioprio", "auto_da_alloc", "noauto_da_alloc"], "pair": {"journal_dev":{\ "options":re.compile(".+"), "incompatible":[]}, "data":{"options":["journal", "ordered", "writeback"], "incompatible":["journal", "ordered", "writeback"]}, "commit":{"options":re.compile("\d+"), "incompatible":[]}, "errors":{"options":["continue", "remount-ro", "panic"], "incompatible":["continue", "remount-ro", "panic"]}, "data_err":{"options":["abort", "ordered", "ignore"], "incompatible":["abort", "ordered", "ignore"]}, "resgid":{"options":re.compile("\d+"), "incompatible":[]}, "resuid":{"options":re.compile("\d+"), "incompatible":[]}, "sb":{"options":re.compile("\d+"), "incompatible":[]}, "journal":{"options":["update"], "incompatible":[]}, "inode_readahead":{"options":\ re.compile("\d+"), "incompatible":[]}, "stripe":{"options":re.compile("\d+"), "incompatible":[]}, "max_batch_time":{"options":\ re.compile("\d+"), "incompatible":[]}, "journal_ioprio":{"options":\ re.compile("[1-7]"), "incompatible":[]}}, "incompatible":[["oldalloc", "orlov"], ["user_xattr","nouser_xattr"], ["acl", "noacl"], ["bsddf", "minixdf"], ["grpid","bsdgroups"], ["grpid","nogrpid"], ["bsdgroups","sysvgroups"], ["nogrpid","sysvgroups"], ["grpquota","noquota","quota", "usrquota"], ["bh","nobh"], ["delalloc", "nodelalloc"], ["auto_da_alloc", "noauto_da_alloc"]]}, "reiserfs":{"options":["conv","hash","hashed_relocation", "no_unhashed_relocation", "noborder", "nolog", "notail", "replayonly", "resize", "user_xattr", "acl"], "pair":{"hash":{"options":["rupasov", "tea", "r5", "detect"], "incompatible":["rupasov", "tea", "r5", "detect"]}, "resize":{"options":re.compile("\d+"), "incompatible":[]}}, "incompatible":[]}, "xfs":{"options":["allocsize", "attr2", "noattr2", "barrier", "dmapi", "grpid", "bsdgroups", "nogrpid", "sysvgroups", "ihashsize", "ikeep", "noikeep", "inode64", "largeio","nolargeio", "logbufs", "logbsize", "logdev", "rtdev", "mtpt", "noalign", "noatime", "norecovery", "nouuid", "osyncisosync", "uquota", "usrquota", "uqnoenforce", "quota", "pquota", "prjquota", "pqnoenforce", "sunit", "swidth", "swalloc"], "pair":{"allocsize":{"options":re.compile("\d+"), "incompatible":[]}, "ihashsize":{"options":re.compile("\d+"), "incompatible":[]}, "logbufs":{"options":re.compile("\d+"), "incompatible":[]}, "logbsize":{"options":re.compile("\d+"), "incompatible":[]}, "logdev":{"options":re.compile(".+"), "incompatible":[]}, "rtdev":{"options":re.compile(".+"), "incompatible":[]}, "mtpt":{"options":re.compile(".+"), "incompatible":[]}, "sunit":{"options":re.compile("\d+"), "incompatible":[]}, "swidth":{"options":re.compile("\d+"), "incompatible":[]}}, "incompatible":[["attr2", "noattr2"], ["grpid", "bsdgroups"], ["grpid", "nogrpid"], ["bsdgroups", "sysvgroups"], ["nogrpid", "sysvgroups"], ["ikeep", "noikeep"], ["largeio","nolargeio"], ["uquota", "usrquota", "uqnoenforce", "quota"], ["pquota", "prjquota", "pqnoenforce"]]}} listFileSystemCorrupted = [] def __init__(self, clVars): self.clVars = clVars self.varDiskData = self._zipVars('os_disk_dev', 'os_disk_format', 'os_disk_mount', 'os_disk_options', 'os_disk_part', 'os_disk_size') def addFileSystemCorrupted(self, fileSystem): """Add file system with error""" if not fileSystem in self.listFileSystemCorrupted: self.listFileSystemCorrupted.append(fileSystem) def getAllSupportFileSystemOpt(self): """Get list all file system""" return filter(lambda x: not x.startswith("_"), self._fileSystemOpt.keys()) +\ self._propertiesFileSystem.keys() def _getFileSystemData(self, realFileSystem): """Get data in _fileSystemOpt""" return self._fileSystemOpt.get(realFileSystem) def _getFileSystemAllOpt(self, realFileSystem): """Get all options from file system""" data = self._getFileSystemData(realFileSystem) if data: return list(set(data["options"])|\ set(self._fileSystemOpt["_all"]["options"])) else: return [] def _checkExistsOptions(self, realFileSystem, realOptions): """Check exists options""" allOptions = self._getFileSystemAllOpt(realFileSystem) if not allOptions: raise InstallError(_("Unsupported file system %s")%realFileSystem) for opt in realOptions: if not opt in allOptions: self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")%opt) def _checkFileSystemIncompatibleOpt(self, realFileSystem, realOptions): """Check incompatible options from realOptions""" # detect duplicate options dupOptions = filter(lambda x: realOptions.count(x)>1, set(realOptions)) if dupOptions: raise InstallError(_("Duplicate options %s")%", ".join(dupOptions)) realOptions = map(lambda x: x.split("=")[0], realOptions) self._checkExistsOptions(realFileSystem, realOptions) data = self._getFileSystemData(realFileSystem) if data: defIncompatibleOpt = self._fileSystemOpt["_all"]["incompatible"] defIncompatibleOpt = map(lambda x: map(lambda y: y, x), defIncompatibleOpt) listDefIncompatibleOpt = reduce(lambda x,y: x+y, defIncompatibleOpt, []) incompatibleOpt = data["incompatible"] for listOpt in incompatibleOpt: for opt in listOpt: if opt in listDefIncompatibleOpt: defIncompatibleOpt = filter(lambda x: not opt in x, defIncompatibleOpt) incompatibleOpt = defIncompatibleOpt + incompatibleOpt listIncompatibleOpt = reduce(lambda x,y: x+y, incompatibleOpt, []) for option in realOptions: if option in listIncompatibleOpt: dataOpt = filter(lambda x: option in x, incompatibleOpt) if dataOpt: listOpt = filter(lambda x: x!=option, dataOpt[0]) twoOptList = list(set(listOpt)&set(realOptions)) if twoOptList: self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incompatible options") + ":"+\ " " + option + " " + _("and") +\ " " + ",".join(twoOptList)) def _checkPairOpt(self, realFileSystem, realOptions): """Check options from realOptions (option=value)""" # detect duplicate options dupOptions = filter(lambda x: realOptions.count(x)>1, set(realOptions)) if dupOptions: raise InstallError(_("Duplicate options %s")%", ".join(dupOptions)) splOptions = map(lambda x: x.split("=")[0], realOptions) self._checkExistsOptions(realFileSystem, splOptions) dictOpt = {} notPairOpt = [] for opt in realOptions: dataOpt = opt.split("=") if len(dataOpt)==2: nameOpt, valueOpt = dataOpt if not nameOpt in dictOpt: dictOpt[nameOpt] = [] dictOpt[nameOpt].append(valueOpt) elif len(dataOpt)>2: self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")%opt) else: notPairOpt.append(opt) data = self._getFileSystemData(realFileSystem) if data: pairData = {} pairData.update(self._fileSystemOpt["_all"]["pair"]) pairData.update(data["pair"]) allPairOpt = pairData.keys() wrongOpt = list(set(allPairOpt)&set(notPairOpt)) if wrongOpt: self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect options %s")\ %", ".join(wrongOpt)) for nameOpt in dictOpt.keys(): if not nameOpt in allPairOpt: self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")\ %"%s=%s"%(nameOpt,valueOpt)) checkValues = pairData[nameOpt] checkValuesOpt = checkValues["options"] # check options listValues = dictOpt[nameOpt] if type(checkValuesOpt)!=list: if len(listValues)>1: wrongOpt = ",".join(map(lambda x: "%s=%s"%(nameOpt,x), listValues)) self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")\ %wrongOpt) if not checkValuesOpt.search(listValues[0]): self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")\ %"%s=%s"%(nameOpt,listValues[0])) else: wrongValues = list(set(listValues)-set(checkValuesOpt)) if wrongValues: wrongOpt = ",".join(map(lambda x: "%s=%s"%(nameOpt,x), wrongValues)) self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")\ %wrongOpt) checkValuesIncompOpt = checkValues["incompatible"] if checkValuesIncompOpt: incompValues = list(set(listValues)&\ set(checkValuesIncompOpt)) if len(incompValues)>1: wrongOpt = map(lambda x: "%s=%s"%(nameOpt,x), incompValues) self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incompatible options") + ":"+\ " " + wrongOpt[0] + " " + \ _("and") + " " +\ ",".join(wrongOpt[1:])) def _zipVars(self, *argvVarNames): """Get zip() the value of the variable name""" return zip(*map(self.clVars.Get, argvVarNames)) def getDefaultOptFileSystem(self, fileSystem): """Get default properties for fileSystem""" if not fileSystem in self._propertiesFileSystem: fileSystem="default" propertiesFileSystem = self._propertiesFileSystem.copy() return propertiesFileSystem[fileSystem] def getDefaultOptMountPoint(self, mountPoint): """Get default properties for mount point disk""" if not mountPoint in self._diskDefaultMountPoints: if mountPoint.startswith('/'): mountPoint = "default" else: raise InstallError(_("Incorrect mount point %s")%mountPoint) propertiesMountPoints = self._diskDefaultMountPoints.copy() return propertiesMountPoints[mountPoint] def getDefaultOptSwap(self): """Get default properties for swap""" return self._swapDefaultMountPoint def getDefaultOptBind(self): """Get default properties for swap""" return self._bindDefaultMountPoint def __call__(self, optionsDict={}): """Convert dict options (bind options, swap options or disk options)""" optProperties = optionsDict.copy() # bind options if "srcMountPoint" in optProperties: # bind options dictOptions = self.getDefaultOptBind().copy() dictOptions.update(optProperties) return dictOptions optDevice = optProperties["dev"] dataPart = filter(lambda x: x[0]==optDevice, self.varDiskData) if not dataPart: dataPart = [["",False,"","","",""]] dev, format, mount, options, part, size = dataPart[0] dictUpdateProperty = {} if "mountPoint" in optProperties: # Disk options dictOptions = {} optFileSystem = optProperties["fileSystem"] optMountPoint = optProperties["mountPoint"] # if specified mount point empty of default - it is / if not optMountPoint or optMountPoint=="default": optMountPoint = "/" dictUpdateProperty["mountPoint"] = optMountPoint supportedFS = self.getAllSupportFileSystemOpt() # if fs not specified and current fs not supported if not optFileSystem and \ not (format and format in supportedFS): optFileSystem = "default" # if specified fs if optFileSystem: # if specified wrong fs if not optFileSystem in supportedFS: raise InstallError(_("Wrong file system options '%s'")\ %optFileSystem) dictOptions.update(self.getDefaultOptFileSystem(optFileSystem)) if optFileSystem == "noformat": if not format: raise InstallError(\ _("Partition %s is not formatted")%dev) if not options: options = ["noatime"] dictOptions["fileSystem"] = format dictOptions["options"] = [] if optFileSystem in self._propertiesFileSystem: dictUpdateProperty["fileSystem"] = dictOptions["fileSystem"] optOptions = optProperties["options"] flagCheckOptOptions = False if optOptions: if optMountPoint != "/": dictUpdateProperty["options"] = optOptions else: flagCheckOptOptions = True optProperties = dict(filter(lambda x: x[1], optProperties.items())) optProperties.update(dictUpdateProperty) if dictOptions: dictDefault = dictOptions.copy() else: dictDefault = self.getDefaultOptMountPoint(optMountPoint).copy() dictDefault.update(optProperties) if flagCheckOptOptions: # Check mount options self._checkFileSystemIncompatibleOpt(dictDefault["fileSystem"], dictDefault["options"]) self._checkPairOpt(dictDefault["fileSystem"], dictDefault["options"]) return dictDefault else: # Swap options dictOptions = {} optFileSystem = "swap" if optFileSystem != format: dictUpdateProperty["isFormat"] = True dictOptions = self.getDefaultOptSwap().copy() dictOptions.update(optProperties) dictOptions.update(dictUpdateProperty) return dictOptions class cl_install(color_print): """Primary class for templates appling and system installation""" def __init__(self): self.clVars = None self.clTempl = None self.color = True self.listDisksOptions = [] self.listBindsOptions = [] self.listSwapsOptions = [] def colorPrint(self,*argv,**kwarg): if self.color: color_print.colorPrint(self,*argv,**kwarg) else: sys.stdout.write(argv[-1]) sys.stdout.flush() def setNoColor(self): self.color = False def initVars(self): """Primary initialization of variables""" self.clVars = DataVarsInstall() self.clVars.importInstall() self.clVars.flIniFile() def applyTemplatesLive(self): """Apply templates for root of system.""" #self.clVars.Set("cl_root_path","/", True) self.clVars.Set("cl_chroot_path","/", True) self.clVars.Write("cl_pass_action", "template", True) self.clTempl = template(self.clVars) dirsFiles = self.clTempl.applyTemplates() if self.clTempl.getError(): self.printERROR(self.clTempl.getError()) return False else: return dirsFiles def printInfo(self,sourceDistr,targetDistr): self.printSUCCESS(_("Installation") + " Calculate Linux") self.defaultPrint("%s\n"%_("System information")) self.printSUCCESS(_("Computer name")+": %s"% self.clVars.Get('os_net_hostname')) self.printSUCCESS(_("Domain name")+": %s"% self.clVars.Get('os_net_domain')) self.printSUCCESS(_("Network devices")+": %s"% self.clVars.Get("os_net_interfaces_info")) self.printSUCCESS(_("Installed system")+": %s %s"% (self.clVars.Get('os_linux_name'), self.clVars.Get('os_linux_ver'))) self.defaultPrint("%s\n"%_("Hardware")) self.printSUCCESS(_("Machine hardware name")+": %s"% self.clVars.Get('os_arch_machine')) self.printSUCCESS(_("Quantity processors")+": %s"% self.clVars.Get('hr_cpu_num')) self.printSUCCESS(_("Videocard vendor")+": %s"% self.clVars.Get('hr_video')) self.printSUCCESS(_("Screen resolution")+": %s"% self.clVars.Get('os_x11_standart')) self.defaultPrint("%s\n"%_("Localization")) self.printSUCCESS(_("Language")+": %s"% self.clVars.Get('os_install_locale_lang')) self.printSUCCESS(_("Keymap")+": %s"% self.clVars.Get('os_install_locale_xkbname')) self.printSUCCESS(_("Timezone")+": %s"% self.clVars.Get('os_install_clock_timezone')) #self.defaultPrint("%s\n"%_("Location")) title, headerList, dataList = self.generateTableData() tableObj = tableReport(title, headerList, dataList) tableObj.printReport(False) title, headerList, dataList = self.generateTableBindData() tableObj = tableReport(title, headerList, dataList) tableObj.printReport(False) self.defaultPrint("%s\n"%_("Network services")) self.printSUCCESS(_("Authentification")+": %s"% "") self.printSUCCESS(_("PROXY")+": %s"% "") self.printSUCCESS(_("NTP")+": %s"% "") self.defaultPrint("%s\n"%_("Perform pre-install checkups")) subname = self.clVars.Get('os_install_linux_subname') subname = (" %s"%subname) if subname else "" if self.clVars.Get('cl_image'): self.printSUCCESS("Found update: %s%s %s\n"% (self.clVars.Get('os_install_linux_name'), subname, self.clVars.Get('os_install_linux_ver'))) else: self.printWARNING("No update available.") def wait(self,sec=10): self.printSUCCESS(_("Press %s to cancel")%"Ctrl+C"+"... %d"%sec, printBR=False) for i in xrange(sec,0,-1): self.defaultPrint("\a\b\b %d" % i) sleep(1) self.defaultPrint("\b\b \n") def prepareBoot(self,targetDistr, grubDisk="0"): self.installBootloader(targetDistr, grubDisk="0") def getTargetDistributive(self,disk,fileSystem="reiserfs",isFormat=False, systemId=None): #if buildermode: #return ScratchDistributive(disk,mdirectory="/mnt/install", #check=True) #else: return PartitionDistributive(disk,mdirectory="/mnt/install", check=True, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId) def applyTemplates(self,directory): """Apply templates for root of system.""" #self.clVars.Set("cl_root_path",directory, True) self.clVars.Set("cl_chroot_path",directory, True) self.clVars.Write("cl_pass_action", "install", True) self.clTempl = template(self.clVars) dirsFiles = self.clTempl.applyTemplates() if self.clTempl.getError(): raise InstallError(self.clTempl.getError()) 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], 'isFormat':False, 'destMountPoint':l[1], 'options':['bind'], 'fileSystem':'none'} return map(list2binddict, filter(lambda x: not x[0] in skipSrc and not x[1] in skipDest, zip(self.clVars.Get('os_install_bind_dir'), self.clVars.Get('os_install_bind_mountpoint')))) def setInstallOptions(self, listDisks, listBinds, listSwaps): """Set data for installation partitions""" convObj = convertDictOpt(self.clVars) try: listDisks = map(convObj, listDisks) # detect previous system if not specified root partition if not filter(lambda x: x['mountPoint'] == '/',listDisks): prevRootDev = self.detectPreviousSystem() if prevRootDev: listDisks += map(convObj, [{'mountPoint': '', 'options': [], 'dev': prevRootDev[0], 'fileSystem': ''}]) listBinds = map(convObj, listBinds) listSwaps = map(convObj, listSwaps) except InstallError,e: self.printERROR(str(e)) if convObj.listFileSystemCorrupted: 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)) 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 # root partition needed listRootDict = filter(lambda x: x['mountPoint'] == '/', listDisks) if not listRootDict: self.printERROR(_("Need specify root partition")) return False # detect duplicate mountPoints dupPoint = filter(lambda x: cmdMountPoints.count(x)>1, set(cmdMountPoints)) if dupPoint: self.printERROR(_("Duplicate mount points %s")\ %", ".join(dupPoint)) return False rootDev = listRootDict[0]['dev'] # find device on loaded system and check mounted loadMount = filter(lambda x:x[0] == rootDev and x[1] != '', 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"]) 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) 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 return True def getDeviceByField(self,field,value, secondPrefix="os_disk"): """Get device by fields (install load format uuid grub part name)""" return self.getFieldByField('dev',field,value, secondPrefix=secondPrefix) def getFieldByField(self,resField,field,value, firstPrefix="os_disk", secondPrefix="os_disk"): res = filter(lambda x: x[1] == value, zip(self.clVars.Get('%s_%s'%(firstPrefix,resField)), self.clVars.Get('%s_%s'%(secondPrefix,field)))) or\ [("","")] return res[0][0] def getFieldByDevice(self,field,device): """Get value of field by device""" device_hash = self.clVars.Get('os_disk_hash') if device in device_hash and field in device_hash[device]: return device_hash[device][field] else: return "" def detectPreviousSystem(self): """Detect previous system""" calculate1ini = "/etc/calculate/calculate.ini" calculate1param = "install.devfrom" if pathexists(calculate1ini): return reduce(lambda x,y: [y.rpartition('=')[2].strip()], filter(lambda x: x.partition("=")[0] == calculate1param, open(calculate1ini,"r")), None) def installBootloader(self,target, grubDisk="0"): """Install boot loader Perform grub installation to disk, which has root partition """ pipe = Popen(["/sbin/grub", "--device-map=%s/boot/grub/device.map"%target.getDirectory(), "--batch"], stdin=PIPE, stdout=PIPE,stderr=PIPE) bootDisk = self.getFieldByField("grub","mount","/boot", secondPrefix="os_install_disk") if not bootDisk: bootDisk = self.getFieldByField("grub","mount","/", secondPrefix="os_install_disk") pipe.stdin.write("root (hd%s)\n" %bootDisk) # TODO: change hd0 for bootloader install to other disks # may be another parameters pipe.stdin.write("setup (hd%s)\n"%grubDisk) pipe.stdin.write("quit\n") pipe.stdin.close() # TODO: break if command is hang (KeyboardInterrupt is supported) if pipe.wait() != 0: raise DistributiveError("Cann't install bootloader") def generateTableData(self): """Get data from print table""" title = _("Location") allDevicesOpt = self.listDisksOptions + self.listSwapsOptions listIsFormat = [] for dev in self.clVars.Get('os_disk_dev'): devCmdOpt = filter(lambda x: x['dev']==dev, allDevicesOpt) if devCmdOpt: if devCmdOpt[0]["isFormat"]: listIsFormat.append(_("Yes")) else: listIsFormat.append("") else: listIsFormat.append("") fileSystemData = zip(self.clVars.Get('os_install_disk_format'), self.clVars.Get('os_disk_format')) listFileSystem = map(lambda x: x[0] if x[0] else x[1], fileSystemData) #fileSystemData = zip(listFileSystem, #self.clVars.Get('os_disk_format')) #listFileSystem = map(lambda x:\ #x[0] if x[0]==x[1] else "%s -> %s" %(x[1], x[0]), #fileSystemData) listMountPoint = map(lambda x: "" if x=="swap" else x, self.clVars.Get('os_install_disk_mount')) partData = zip(self.clVars.Get('os_disk_size'), self.clVars.Get('os_disk_part')) listSize = map(lambda x: "" if x[1]=="extended" else x[0], partData) headerList = [_("Size"),_("Device"),_("Directory"),_("File system"), _("Format"), _("Partition")] dataList = map(lambda x:x[:-1], filter(lambda x:x[-1] != "", zip(listSize, self.clVars.Get('os_disk_dev'), listMountPoint, listFileSystem, listIsFormat, self.clVars.Get('os_disk_part'), self.clVars.Get('os_install_disk_mount')))) return title, headerList, dataList def generateTableBindData(self): """Get bind data for print table""" title = _("Bind mounts") headerList = [_("Source directory"),_("Mount point")] return title, headerList, zip(self.clVars.Get('os_install_bind_dir'), self.clVars.Get('os_install_bind_mountpoint')) def getPwdHashUser(self, userName): cl_overriding.printSUCCESS(_("Enter password for user %s") %userName) userPwd = getUserPassword() if userPwd is False: return False encryptObj = encrypt() pwdHash = encryptObj.getHashPasswd(userPwd, "shadow_ssha256") if pwdHash is False: return False return pwdHash def generateHashUsers(self, users): """Generate pwd hash from users""" listAddUsers = [] for user in users: hashFuct = lambda x: self.getPwdHashUser(x) listAddUsers.append((user, hashFuct)) return listAddUsers def generateHashRoot(self): """Generate pwd hash from root""" hashFuct = lambda x: self.getPwdHashUser(x) return [("root", hashFuct,"","")] def configureSystem(self): """configure current system""" self.printSUCCESS("Configurating system") error = None try: if self.clVars.Get('os_root_type') == "livecd": self.applyTemplatesLive() except (InstallError,DistributiveError),e: error = e except (Exception),e: error = "" for i in apply(traceback.format_exception, sys.exc_info()): error += i except KeyboardInterrupt,e: self.defaultPrint("\n") self.printWARNING("Interrupting the configuration") error = _("Configuration manually interrupt") if error: for line in filter(lambda x: x,str(error).split('\n')): self.printERROR(line) self.printERROR(_("System configuration failed")) return False return True def installSystem(self, force=False, bootDisk=None, users=[]): """install System by current variable enviroment""" if not users: users = [] sourceDistr = None targetDistr = None error = None try: rootPartdev = self.clVars.Get('os_install_root_dev') rootPartCmdList = filter(lambda x: x['dev']==rootPartdev, self.listDisksOptions) rootPartCmdDict = rootPartCmdList[0] rootPartFileSystem = self.getFieldByField("format","dev", rootPartdev, firstPrefix="os_install_disk") rootPartIsFormat=rootPartCmdDict['isFormat'] rootPartSystemId=rootPartCmdDict['systemId'] # wait 10 sec #waittime = 3 #self.printSUCCESS(_("Installation will start pass %d seconds.") #%waittime) bootDiskGrub = "" if bootDisk: listbootDiskGrub = map(lambda x: x[1], filter(lambda x: "/dev/"+x[0]==bootDisk, zip(self.clVars.Get('os_device_dev'), self.clVars.Get('os_device_map')))) if listbootDiskGrub: bootDiskGrub=listbootDiskGrub[0] else: raise InstallError(_("Cann't found disk %s")%bootDisk) self.printInfo(sourceDistr,targetDistr) targetDistr = self.getTargetDistributive(rootPartdev, fileSystem=rootPartFileSystem, isFormat=rootPartIsFormat, systemId=rootPartSystemId) distRep = DistributiveRepository() distName = self.clVars.Get('cl_image') if distName: # print info sourceDistr = distRep.getDistributiveByFile(distName) if not force: dialogMessage = _("Continue with the installation of \ the system") + " (yes/no)" dialogRes = dialogYesNo(dialogMessage) if dialogRes is None: return True elif dialogRes is False: return True #self.wait(waittime) # cmd options #self.listDisksOptions #self.listBindsOptions #self.listSwapsOptions noRootPartDisksOptions = filter(lambda x: x['mountPoint']!="/", self.listDisksOptions) flagMultipartition = False objMultiPartitions = False # Disk multipartitions if noRootPartDisksOptions: flagMultipartition = True objMultiPartitions = MultiPartitions() for diskOptions in noRootPartDisksOptions: dev = diskOptions["dev"] mountPoint = diskOptions["mountPoint"] fileSystem = diskOptions["fileSystem"] isFormat = diskOptions["isFormat"] systemId = diskOptions["systemId"] objMultiPartitions.addPartition(dev=dev, mountPoint=mountPoint, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId) # Swap multipartitions if self.listSwapsOptions: flagMultipartition = True if not objMultiPartitions: objMultiPartitions = MultiPartitions() for diskOptions in self.listSwapsOptions: dev = diskOptions["dev"] mountPoint = "swap" fileSystem = diskOptions["fileSystem"] isFormat = diskOptions["isFormat"] systemId = diskOptions["systemId"] objMultiPartitions.addPartition(dev=dev, mountPoint=mountPoint, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId) # Bind multipartitions if self.listBindsOptions: flagMultipartition = True if not objMultiPartitions: objMultiPartitions = MultiPartitions() for diskOptions in self.listBindsOptions: dev = diskOptions["srcMountPoint"] mountPoint = diskOptions["destMountPoint"] fileSystem = "bind" isFormat = diskOptions["isFormat"] objMultiPartitions.addPartition(dev=dev, mountPoint=mountPoint, fileSystem=fileSystem, isFormat=isFormat) self.printSUCCESS(_("Formating partitions")) if flagMultipartition: # Set Multipartition targetDistr.multipartition=objMultiPartitions # Format all partitions targetDistr.formatAllPartitions() else: # Format root partition if targetDistr.isFormat: targetDistr.formatPartition(targetDistr.partition, format=targetDistr.fileSystem) # install distributive self.printSUCCESS(_("Unpacking system image into target")) targetDistr.installFrom(sourceDistr) self.printOK("Unpacking complete") # join templates self.printSUCCESS(_("Update config")) self.applyTemplates(targetDistr.getDirectory()) # mount bind mount points targetDistr.postinstallMountBind() # migrate users self.printSUCCESS(_("Migrate users")) addUsers = self.generateHashUsers(users) changePwdUsers = self.generateHashRoot() objMigrate = migrate(targetDistr.getDirectory()) if not objMigrate.migrate(addUsers, changePwdUsers): raise InstallError(_("Can not migrate users to new system")) # change boot config self.printSUCCESS(_("Prepare system for reboot")) if bootDiskGrub: self.prepareBoot(targetDistr, bootDiskGrub) else: self.prepareBoot(targetDistr) else: return False except (InstallError,DistributiveError),e: error = e #for i in apply(traceback.format_exception, sys.exc_info()): # print i except (Exception),e: error = "" for i in apply(traceback.format_exception, sys.exc_info()): error += i except KeyboardInterrupt,e: self.defaultPrint("\n") self.printWARNING("Interrupting the installation") error = _("Installation manually interrupt") try: if self.clTempl: self.clTempl.closeFiles() if sourceDistr: self.printSUCCESS(_("Releasing source distributive")) sourceDistr.close() if targetDistr: self.printSUCCESS(_("Unmount target system volume")) targetDistr.close() except (InstallError,DistributiveError),e: error = "%s\n%s" % (str(error),_("Unmounting error")) except KeyboardInterrupt,e: pass if error: for line in filter(lambda x: x,str(error).split('\n')): self.printERROR(line) self.printERROR(_("System installation failed")) return False self.printSUCCESS(_("System successfully installed")) return True def setLinuxName(self,shortname): self.clVars.Set('os_install_linux_shortname',shortname,True) def setAllLocaleByLang(self,lang): """Set all locale variable by specified lang""" locale = clLocale() if not locale.isLangExists(lang): return False self.clVars.Set('os_install_locale_lang',lang, True) self.clVars.Set('os_install_locale_locale', locale.getFieldByLang('locale',lang), True) self.clVars.Set('os_install_locale_language', locale.getFieldByLang('language',lang), True) self.clVars.Set('os_install_locale_keymap', locale.getFieldByLang('keymap',lang), True) self.clVars.Set('os_install_locale_dumpkeys', locale.getFieldByLang('dumpkeys_charset',lang), True) self.clVars.Set('os_install_locale_xkb', locale.getFieldByLang('xkblayout',lang), True) return True