#-*- coding: utf-8 -*- # Copyright 2010 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.9" __app__ = "calculate-install" import os import re import sys import traceback from os import path from cl_utils import runOsCommand,appendProgramToEnvFile, \ removeProgramToEnvFile,pathJoin, \ scanDirectory,process,getTupleVersion, \ detectDeviceForPartition,listDirectory from cl_kernel_utils import KernelConfig,InitRamFs import cl_overriding from StringIO import StringIO 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"] def pop_install_errors(): res = globals()["install_errors"] globals()["install_errors"] = "" return res defaultExit = cl_overriding.exit defaultPrintERROR = cl_overriding.printERROR 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, ScratchPartitionDistributive, \ MultiPartitions, Spinner, FlashDistributive, SignalInterrupt,\ Distributive from cl_string import tableReport from time import sleep from subprocess import PIPE,STDOUT from server.utils import dialogYesNo from cl_migrate_users import migrate, currentUsers from cl_utils import getUserPassword from encrypt import encrypt from shutil import copy2 from cl_lang import lang lang().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 = "install" # заполнить переменные окружения алгоритмом по умолнанию self.importData(envSection, ('cl_vars_install','cl_fill_install')) class convertDictOpt: """Convert dict install option""" _defaultFS = "reiserfs" _defaultFlashFS = "vfat" _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":["noatime"]}, "noformat":{"fileSystem":"", "isFormat":False, "options":["noatime"]}, "defaultflash":{"fileSystem":_defaultFlashFS, "isFormat":True, "options":["noatime"]}} _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"]], "makefs":"/sbin/mkfs.ext2"} _ext3Options = _ext2Options.copy() _ext3Options.update({"makefs":"/sbin/mkfs.ext3"}) _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"]], "makefs":"/sbin/mkfs.ext4"}, "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":[], "makefs":"/sbin/mkfs.reiserfs"}, "vfat":{"options":["uni_xlate","posix","nonumtail", "utf8","shortname"], "pair":{"shortname":{"options": re.compile("lower|win95|winnt|mixed"), "incompatible":[]}, "utf8":{"options": re.compile("0|1|no|false|true|yes"), "incompatible":["uni_xlate"]}}, "incompatible":[], "makefs":"/usr/sbin/mkfs.vfat"}, "ntfs":{"options":["uni_xlate","posix","nls", "utf8","iocharset", "uid","gid","umask"], "pair":{"utf8":{"options": re.compile("0|1|no|false|true|yes"), "incompatible":["uni_xlate"]}, "iocharset":{"options":re.compile(".+"), "incompatible":["nls"]}, "uni_xlate":{"options": re.compile("0|1|2"), "incompatible":[]}, "posix":{"options": re.compile("0|1"), "incompatible":[]}, "uid":{"options":re.compile(".+"), "incompatible":[]}, "gid":{"options":re.compile(".+"), "incompatible":[]}, "umask":{"options":re.compile(".+"), "incompatible":[]}, }, "incompatible":[], "makefs":"/usr/sbin/mkfs.ntfs"}, "ntfs-3g":{"options":["uid","gid","umask","fmask", "dmask","usermapping", "default_permissions", "inherit","locale", "force","remove_hiberfile", "show_sys_files","allow_other", "max_read","silent","no_def_opts", "streams_interface","user_xattr", "efs_raw","debug","no_detach"], "pair":{"uid":{"options":re.compile(".+"), "incompatible":[]}, "gid":{"options":re.compile(".+"), "incompatible":[]}, "umask":{"options":re.compile(".+"), "incompatible":[]}, "fmask":{"options":re.compile(".+"), "incompatible":[]}, "dmask":{"options":re.compile(".+"), "incompatible":[]}, "usermapping":{"options":re.compile(".+"), "incompatible":[]}, "default_permissions":{ "options":re.compile(".+"), "incompatible":[]}, "locale":{"options":re.compile(".+"), "incompatible":[]}, "max_read":{"options":re.compile(".+"), "incompatible":[]}, "streams_interface":{ "options":re.compile(".+"), "incompatible":[]}}, "incompatible":[], "makefs":"/usr/sbin/mkfs.ntfs"}, "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"]], "makefs":"/sbin/mkfs.xfs"}} 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 getAllAvailableFileSystemOpt(self): return filter(lambda x: x in ("default","noformat","defaultflash") or (not "makefs" in self._fileSystemOpt[x] or path.exists(self._fileSystemOpt[x]["makefs"])), self.getAllSupportFileSystemOpt()) 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 opt and 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, devicetype="hdd"): """Get default properties for fileSystem""" if not fileSystem in self._propertiesFileSystem: fileSystem="default" if devicetype == "flash" and fileSystem=="default": fileSystem="defaultflash" if devicetype != "flash" and fileSystem=="defaultflash": 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 _getDeviceType(self,dev): """Get device type, considing given by user param""" oldRootDev = self.clVars.Get('os_install_root_dev') self.clVars.Set('os_install_root_dev',dev,True) rootType = self.clVars.Get('os_install_root_type') self.clVars.Set('os_install_root_dev',oldRootDev,True) return rootType 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"] if optProperties["mountPoint"]: optMountPoint = path.normpath(optProperties["mountPoint"]) else: 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() reRootDirectories = re.compile("^/[^/]*/?$",re.S) if reRootDirectories.match(path.normpath(optMountPoint)): # check install type (flash or hdd) if self._getDeviceType(dev) != "flash": excludeFS = set(["vfat","ntfs","ntfs-3g"]) else: excludeFS = set(supportedFS) - \ set(["vfat","noformat","default"]) else: excludeFS = set([]) availableFS = self.getAllAvailableFileSystemOpt() # if fs not specified and current fs not supported if not optFileSystem: if not (format and format in set(supportedFS)-excludeFS): optFileSystem = "default" else: dictUpdateProperty["fileSystem"] = format # if specified fs if optFileSystem: # if specified wrong fs if not optFileSystem in supportedFS: raise InstallError(_("Wrong file system options '%s'")\ %optFileSystem) if not optFileSystem in availableFS: raise InstallError(_("File system '%s' is not available")\ %optFileSystem) if optFileSystem in excludeFS: mp = optMountPoint if reRootDirectories.match(path.normpath(mp)) \ and self._getDeviceType(dev) == "flash": mp = "flash" raise InstallError( _("File system for '%(mp)s' should not be '%(opt)s'") %{'mp':mp, 'opt':optFileSystem}) if not "fileSystem" in dictOptions or optFileSystem == "default": dictOptions.update( self.getDefaultOptFileSystem(optFileSystem, self._getDeviceType(dev))) if optFileSystem == "noformat": if not format: raise InstallError(\ _("Partition %s is not formatted")%dev) elif format in excludeFS: mp = optMountPoint if reRootDirectories.match(path.normpath(mp)) \ and self._getDeviceType(dev) == "flash": mp = "flash" raise InstallError(\ _("File system for '%(mp)s' should not be '%(format)s'")\ %{'mp':mp,'format':format}) if not options: options = ["noatime"] dictOptions["fileSystem"] = format dictOptions["options"] = [] if optFileSystem in self._propertiesFileSystem: dictUpdateProperty["fileSystem"] = dictOptions["fileSystem"] optOptions = optProperties["options"] flagCheckOptOptions = True 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 cltCopy(scanDirectory): """Copy clt files Example: cltCopier = cltCopy(target="/targetdir") # copy all clt files from etc directory to /targetdir/etc cltCopier.performCopy('/etc') """ def __init__(self,target='/tmp'): self.target = target performCopy = scanDirectory.scanningDirectory def processingFile(self,pathname,prefix): try: if pathname.endswith(".clt"): targetDir = pathJoin(self.target,path.dirname(pathname)) if not path.exists(targetDir): os.makedirs(targetDir) copy2(pathname,pathJoin(self.target,pathname)) except Exception,e: raise InstallError(_("Can not copy '%(src)s' to '%(dst)s'")% {'src':pathname,'dst':pathJoin(self.target,pathname)}) return True class otherfilesCopy(scanDirectory): """Copy some files Example: otherfilesCopier = otherfilesCopy(target="/targetdir") # copy need files from etc directory to /targetdir/etc otherfilesCopier.performCopy('/etc') """ def __init__(self,target='/tmp',reTest=".*"): self.target = target self.reTest = re.compile(reTest,re.S) performCopy = scanDirectory.scanningDirectory def processingFile(self,pathname,prefix): try: if self.reTest.search(pathname): targetDir = pathJoin(self.target,path.dirname(pathname)) if not path.exists(targetDir): os.makedirs(targetDir) copy2(pathname,pathJoin(self.target,pathname)) except Exception,e: raise InstallError(_("Can not copy '%(src)s' to '%(dst)s'")% {'src':pathname,'dst':pathJoin(self.target,pathname)}) return True class cl_install(color_print, SignalInterrupt): """Primary class for templates appling and system installation""" def __init__(self): self.clVars = None self.clTempl = None self.listDisksOptions = [] self.listBindsOptions = [] self.listSwapsOptions = [] self.startMessage = "" self.lenStartMessage = 0 self.stdoutHide = None self.stderrHide = None Spinner().setWriteFunc(self.defaultPrint) 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.clTempl = template(self.clVars,cltFilter=False) dirsFiles = self.clTempl.applyTemplates() if self.clTempl.getError(): self.printERROR(self.clTempl.getError()) return False else: return dirsFiles def printInfo(self): self.printSUCCESS(_("Installation") + " Calculate Linux") self.defaultPrint("%s\n"%_("System information")) self.printSUCCESS(_("Computer name")+": %s"% self.clVars.Get('os_install_net_hostname')) self.printSUCCESS(_("Domain name")+": %s"% self.clVars.Get('os_install_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_install_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_install_x11_resolution')) 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")) mbrDevice = self.clVars.Get('os_install_mbr') addonMbrInfo = "" if not mbrDevice in ("","off"): pathVendor = "/sys/block/%s/device/vendor"%mbrDevice pathModel = "/sys/block/%s/device/model"%mbrDevice if path.exists(pathVendor) and path.exists(pathModel): addonMbrInfo = " (%s %s)"% \ (open(pathVendor,'r').read().strip(), open(pathModel,'r').read().strip()) self.printSUCCESS(_("Master boot record")+" (MBR): /dev/%s%s"% (self.clVars.Get('os_install_mbr'),addonMbrInfo)) else: self.printSUCCESS(_("Master boot record")+ " (MBR): %s"%_("not changed")) title, headerList, dataList = self.generateTableData() tableObj = tableReport("", headerList, dataList) tableObj.printReport(False) title, headerList, dataList = self.generateTableBindData() if dataList: tableObj = tableReport(title, headerList, dataList) tableObj.printReport(False) self.defaultPrint("%s\n"%_("Network services")) #self.printSUCCESS(_("Authentification")+": %s"% # "") self.printSUCCESS(_("PROXY")+": %s"% (self.clVars.Get('os_install_proxy') or _("none"))) self.printSUCCESS(_("NTP")+": %s"% (self.clVars.Get('os_install_ntp') or _("none"))) self.defaultPrint("%s\n"%_("Perform pre-install checkups")) subname = self.clVars.Get('os_install_linux_subname') subname = (" %s"%subname) if subname else "" buildvar = self.clVars.Get('os_install_linux_build') build = "" if buildvar: build = " (build %s)"%buildvar if self.clVars.Get('cl_image'): self.printSUCCESS(_("Found update")+": %s %s%s%s\n"% (self.clVars.Get('os_install_linux_name'), self.clVars.Get('os_install_linux_ver'), subname,build)) else: self.printWARNING(_("No update available.")) def prepareBoot(self,targetDistr): """Prepare system for boot""" if self.clVars.Get('os_install_root_type') == "flash": self.installSyslinuxBootloader(targetDistr) else: self.installGrubBootloader(targetDistr) def getTargetDistributive(self,disk,fileSystem="reiserfs",isFormat=False, systemId=None,buildermode=False): """Get target distributive by params""" rootLabelName = "%s-%s"%(self.clVars.Get('os_install_linux_shortname'), self.clVars.Get('os_install_linux_ver')) mapDevice = self.clVars.Get('os_device_hash') mapPartPT = dict( map(lambda x:[x,mapDevice.get(detectDeviceForPartition(x), {'table':None})['table']], self.clVars.Get('os_disk_dev'))) if buildermode: return ScratchPartitionDistributive(disk,mdirectory="/mnt/install", check=True, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId, rootLabel=rootLabelName, partitionTable=mapPartPT.get(disk,None)) elif self.clVars.Get('os_install_root_type')=="flash": return FlashDistributive(disk,mdirectory="/mnt/install", check=True, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId, partitionTable=mapPartPT.get(disk,None)) else: target = PartitionDistributive(disk,mdirectory="/mnt/install", check=True, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId, rootLabel=rootLabelName, partitionTable=mapPartPT.get(disk,None)) 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"] partitionTable = mapPartPT.get(dev,None) objMultiPartitions.addPartition(dev=dev, mountPoint=mountPoint, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId, partitionTable=partitionTable) # 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"] partitionTable = mapPartPT.get(dev,None) objMultiPartitions.addPartition(dev=dev, mountPoint=mountPoint, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId, partitionTable=partitionTable) # 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, systemId=None, partitionTable=None) if flagMultipartition: # Set Multipartition target.multipartition=objMultiPartitions return target def closeClTemplate(self): if self.clTempl: if self.clTempl.cltObj: self.clTempl.cltObj.closeFiles() self.clTempl.closeFiles() self.clTempl = None def applyTemplatesFlash(self,directory): """Apply templates for root of system.""" #self.clVars.Set("cl_root_path",directory, True) self.clVars.Set("cl_chroot_path","/", True) self.clVars.Set("cl_root_path",directory, True) self.clTempl = template(self.clVars,cltObj=False) dirsFiles = self.clTempl.applyTemplates() if self.clTempl.getError(): raise InstallError(self.clTempl.getError()) else: return dirsFiles 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) clTemplateCltPath = \ filter(lambda x:path.exists(x), map(lambda x:pathJoin(directory,x), self.clVars.Get('cl_template_clt_path'))) self.clVars.Set('cl_template_clt_path',clTemplateCltPath,True) self.clTempl = template(self.clVars,cltFilter=False) dirsFiles = self.clTempl.applyTemplates() if self.clTempl.getError(): raise InstallError(self.clTempl.getError()) else: return dirsFiles def setDisks(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.clVars.Get('os_install_dev_from') if prevRootDev: listDisks += map(convObj, [{'mountPoint': '', 'options': ['noatime'], 'dev': prevRootDev, '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 # break perform if disk params empty and os_install_dev_from empty if not (listDisks or listSwaps or listBinds): return True 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 mount options for scratch and flash if filter(lambda x: x != '/', usedMP): if self.clVars.Get('os_install_scratch') == "on": self.printERROR( _("Builder mode is not support multipartition")) return False # check specified devices wrongDevices = list(set(usedDevicesOnlyDisks) - \ set(self.clVars.Get('os_disk_dev'))) wrongDevices = 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')))) usingExtPart = list(set(usedDevices)&set(extendedPartitions)) if usingExtPart: self.printERROR(_("Can not use extended partition %s")% usingExtPart[0]) 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 %(src)s already use "\ "for bind '%(bindSrc)s' to '%(bindDst)s'")\ %{'src':wrongBind[0], 'bindSrc':incompBind[0][0], 'bindDst':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 mount point (bind '%(bindSrc)s' to "\ "'%(bindDst)s')")\ %{'bindSrc':wrongBind[0][0], 'bindDst':wrongBind[0][1]}) 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 mount 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 and x != "none", usedMP))) if dupMP: self.printERROR(_("Mount point '%s' is used twice")%dupMP[0]) return False def clearParam(data,isswap): if builderMode: if len(listSwaps) == 0 and isswap == "swap": return data else: if len(listSwaps) == 0 or isswap != "swap": return data return "" builderMode = self.clVars.Get('os_install_scratch') == "on" clearBuilder = lambda data,isswap: "" if builderMode and isswap != "swap" else data # get hash from current variables devMount = dict(map(lambda x:(x[0], {'mountPoint':clearParam(x[1],x[1]), 'fileSystem':x[2], 'options':clearParam(x[3],x[1]), 'isFormat':""}), 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')))) curDevMount = dict(zip(self.clVars.Get('os_disk_dev'), self.clVars.Get('os_disk_mount'))) 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 = curDevMount[dev] if curMP and ( curMP != mountPoint and isFormat or curMP == '/' ): self.printERROR(_("Specified disk '%s' mounted to")\ %dev + " " + _("'%s' in current system")\ %curMP) return False else: if mountPoint and 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" if builderMode: bindDestSrc = {} bindSrcDest = {} else: bindDestSrc =dict(zip(self.clVars.Get('os_install_bind_mountpoint'), self.clVars.Get('os_install_bind_path'))) bindSrcDest = dict(zip(self.clVars.Get('os_install_bind_path'), 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 install root dev rootDev = filter(lambda x:x[1]['mountPoint']=='/',devMount.items()) if not rootDev: self.printERROR(_("Need specify root partition")) return False self.clVars.Set('os_install_root_dev',rootDev[0][0],True) osInstallRootType = self.clVars.Get('os_install_root_type') # update bind variables by new hash if osInstallRootType != "flash": new_bind_dest, new_bind_src = \ reduce(lambda x,y:[x[0]+[y[0]],x[1]+[y[1]]], sorted(bindDestSrc.items()) , [[]]*2) # discard all bind point for flash installation else: new_bind_dest = [] new_bind_src = [] if filter(lambda x: x != '/', usedMP): self.printERROR( _("Installation to flash disk is not support multipartition")) return False if filter(lambda x:x['dev']!="none",listSwaps): self.printERROR( _("Installation to flash disk is not support swap disks")) return False if builderMode: self.printERROR( _("Installation to flash disk is not support builder mode")) return False # receive substitution func. Discard all mp, exclude '/' for flash if osInstallRootType != "flash": substitution = lambda data,mp: data else: substitution = lambda data,mp: data if mp == '/' else "" separateDevice = lambda device: map( lambda x: int(x) if x.isdigit() else x, re.findall('\d+|\D+',device)) # update variables by new hash new_mount, new_format, new_isformat, new_options= \ reduce(lambda x,y:[x[0]+[substitution(devMount[y]['mountPoint'], devMount[y]['mountPoint'])], x[1]+[substitution(devMount[y]['fileSystem'], devMount[y]['mountPoint'])], x[2]+[substitution(devMount[y]['isFormat'], devMount[y]['mountPoint'])], x[3]+[substitution(devMount[y]['options'], devMount[y]['mountPoint'])]], sorted(devMount.keys(),key=separateDevice),[[]]*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_path',new_bind_src), ('os_install_bind_mountpoint',new_bind_dest))) return True def setUsers(self,listUsers): """Set users data (migration)""" if listUsers: migrateUsers = list(set(listUsers)) migrateUsers.sort() migrateUsers = ["root"] + filter(lambda x: x!="root", migrateUsers) self.clVars.Set('cl_migrate_user', migrateUsers, force=True) return True def setMBR(self, mbrDisk): """Set mbr by param or get from variables""" bootDiskGrub = "" if mbrDisk == "off": self.clVars.Set('os_install_mbr',"",force=True) elif mbrDisk: listbootDiskGrub = map(lambda x: x[0], filter(lambda x: "/dev/"+x[0]==mbrDisk, zip(self.clVars.Get('os_device_dev'), self.clVars.Get('os_device_map')))) if filter(lambda x: "/dev/%s"%x == mbrDisk, self.clVars.Get('os_device_dev')): self.clVars.Set('os_install_mbr',mbrDisk[5:], force=True) else: self.printERROR(_("Cann't found disk '%s'")%mbrDisk) return False return True def createListOptions(self): """Create listDisksOptions, listSwapsOptions and listBindOptions by variables""" 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_path'), 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) # update system id 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'))))) for disk in self.listDisksOptions + self.listSwapsOptions: if disk['dev'] in updateIdDict: disk['systemId'] = updateIdDict[disk['dev']] else: disk['systemId'] = None return True def setInstallOptions(self, listDisks, listBinds, listSwaps, listUsers, mbrDisk): """Set install options (set users, disks and mbr""" try: if self.setUsers(listUsers) and \ self.setDisks(listDisks,listBinds,listSwaps) and \ self.setMBR(mbrDisk): return self.createListOptions() else: return False except InstallError,e: self.printERROR(str(e).strip()) return False 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 setActivePartition(self,partition): reActive = re.compile('^%s\s*[*]'%partition) device = filter(lambda x:x in partition, self.clVars.Get('os_device_dev')) if not device: raise DistributiveError(_("Cann't get parent device")) device = device[0] fdiskProcess = process("/sbin/fdisk","-l","/dev/%s"%device) if fdiskProcess.failed(): raise DistributiveError(_("Cann't get device information\n%s")% fdiskProcess.read()) if not filter(reActive.search,fdiskProcess): grubDisk = self.getFieldByField("grub","mount","/", secondPrefix="os_install_disk") if grubDisk and grubDisk.rpartition(',')[2].isdigit(): fdiskProcess = process("/sbin/fdisk", "/dev/%s"%device) fdiskProcess.write("a\n%d\nw\n"% (int(grubDisk.rpartition(',')[2])+1)) if fdiskProcess.success(): return True if filter(reActive.search,process("/sbin/fdisk", "-l","/dev/%s"%device)): return True raise DistributiveError(_("Cann't set active partition")) else: return True def installSyslinuxBootloader(self,target): """Install boot loader by syslinux Perform syslinux installation to flash. """ ddProcess = process("/bin/dd","if=/usr/share/syslinux/mbr.bin", "of=/dev/%s"%self.clVars.Get('os_install_mbr'), stderr=STDOUT) if ddProcess.failed(): raise DistributiveError(_("Cann't write master boot record\n%s")% ddProcess.read()) target.close() installRootDev = self.clVars.Get('os_install_root_dev') syslinuxProcess = process("/usr/bin/syslinux", installRootDev, stderr=STDOUT) if syslinuxProcess.failed(): raise DistributiveError(_("Cann't install syslinux\n%s")% syslinuxProcess.read()) # is partition active return self.setActivePartition(self.clVars.Get('os_install_root_dev')) def installGrubBootloader(self,target): """Install boot loader Perform grub installation to disk, which has root partition """ grubProcess = process("/sbin/grub", "--device-map=%s/boot/grub/device.map"%target.getDirectory(), "--batch",stderr=STDOUT) bootDisk = self.getFieldByField("grub","mount","/boot", secondPrefix="os_install_disk") if not bootDisk: bootDisk = self.getFieldByField("grub","mount","/", secondPrefix="os_install_disk") mbrDisk = self.clVars.Get('os_install_mbr') mbrDiskNum = filter(lambda x:x[0]==mbrDisk, zip(self.clVars.Get('os_device_dev'), self.clVars.Get('os_device_map'))) if not mbrDiskNum: raise DistributiveError(_("Cann't determine mbr disk")) grubProcess.write("root (hd%s)\n" %bootDisk) grubProcess.write("setup (hd%d)\n"%mbrDiskNum[0][1]) grubProcess.write("quit\n") if grubProcess.failed(): 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')) if self.clVars.Get('os_install_scratch') == "on": listMountPoint = map(lambda x: "builder" if x == "/" else x, listMountPoint) 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) if self.clVars.Get('os_install_root_type') == 'flash': headerList = [_("Size"),_("Device"),_("File system"), _("Format"), _("Partition")] colnum = 2 else: headerList = [_("Size"),_("Device"),_("Directory"), _("File system"),_("Format"), _("Partition")] colnum = 3 dataList = map(lambda x:x[:colnum]+x[3:-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_path'), self.clVars.Get('os_install_bind_mountpoint')) def getPwdHashUser(self, userName, stdinRead=False): if stdinRead: try: userPwd = sys.stdin.readline().rstrip() except EOFError: raise KeyboardInterrupt() else: cl_overriding.printSUCCESS(_("Enter password for user %s")%userName) try: userPwd = getUserPassword() while userPwd is False: if get_install_errors(): for line in filter(lambda x:x, pop_install_errors().split('\n')): self.printERROR(line) userPwd = getUserPassword() except EOFError: raise KeyboardInterrupt() encryptObj = encrypt() if not userPwd: raise InstallError(_("Unable to find the password for user %s")\ %userName) return False pwdHash = encryptObj.getHashPasswd(userPwd, "shadow_ssha256") if pwdHash is False: raise InstallError() return pwdHash def getNamesAddUsers(self): """Get names added users""" return map(lambda x: x[0], filter(lambda x: x[1]=="yes",\ zip(self.clVars.Get("cl_migrate_user"), self.clVars.Get("cl_migrate_user_pwd")))) def getNamesMigrateUsers(self): """Get names migrated users""" return map(lambda x: x[0], filter(lambda x: x[1]=="no",\ zip(self.clVars.Get("cl_migrate_user"), self.clVars.Get("cl_migrate_user_pwd")))) def generateHashUsers(self, stdinRead=False): """Generate pwd hash from users""" addUsers = self.getNamesAddUsers() users = filter(lambda x: x!="root", addUsers) listAddUsers = [] for user in users: hashPwd = self.getPwdHashUser(user, stdinRead) listAddUsers.append((user, hashPwd)) return listAddUsers def generateHashRoot(self, stdinRead=False): """Generate pwd hash from root""" addUsers = self.getNamesAddUsers() if filter(lambda x: x=="root", addUsers): hashPwd = self.getPwdHashUser("root", stdinRead) return [("root", hashPwd,"","")] else: return [] def printMessageForTest(self, message, lenMsg=False): """Print waiting message and OK or Error by func result""" message = "%s ..." % message self.printSUCCESS(message,printBR=False) self.startMessage = message if lenMsg: self.lenStartMessage = lenMsg else: self.lenStartMessage = self.lenString(self.startMessage) def printOnlyNotOK(self, string, offsetL=0, printBR=True): """Вывод на печать в случае сбоя""" self._printSysOut = sys.stdout self.printLine((('', string),), (('blueBr','['), ('redBr',' !! '), ('blueBr',']'), ), offsetL, printBR) def printByResult(self,result,failMessage=None): if self.startMessage: offset = 3 if result: self.printOnlyOK(" ", self.lenStartMessage + offset) else: self.printOnlyNotOK(" ", self.lenStartMessage + offset) if failMessage: self.printERROR(failMessage) self.startMessage = "" self.lenStartMessage = 0 def setupOpenGL(self): """Setup opengl for current video driver""" defaultGL = "xorg-x11" pathGlModules = path.join(self.clVars.Get('cl_chroot_path'), 'usr/lib/opengl') openGLenv = path.join(self.clVars.Get('cl_chroot_path'), 'etc/env.d/03opengl') openGlMods = filter(lambda x:x != "global", listDirectory(pathGlModules)) mapGL_drivers = {'fglrx':"ati" if "ati" in openGlMods else defaultGL, 'nvidia':"nvidia" if "nvidia" in openGlMods else defaultGL} x11_driver = self.clVars.Get('os_install_x11_video_drv') if x11_driver in mapGL_drivers: newModuleName = mapGL_drivers[x11_driver] else: newModuleName = defaultGL curModuleName = map(lambda x:x.strip().rpartition('=')[-1].strip('"\''), filter(lambda x: x.startswith("OPENGL_PROFILE="), open(openGLenv,'r'))) curModuleName = curModuleName[-1] if curModuleName else "" if curModuleName == newModuleName: return True res,errmes = runOsCommand('eselect opengl set %s'%newModuleName) if res == 0: return True else: return False def checkVideoDriver(self): """Check video driver and install nvidia driver""" binPackages = '/usr/portage/packages' nvidiaBinDrivers = path.join(binPackages,'x11-drivers') if self.clVars.Get('hr_video') != 'nvidia' or \ not path.exists(nvidiaBinDrivers): return True maskFile = '/etc/portage/package.mask' nvidiaMaskFile = path.join(maskFile,'nvidia-drivers') # convert file package.mask to directory package mask if path.isfile(maskFile): os.rename(maskFile,maskFile+"2") os.mkdir(maskFile,mode=0755) os.rename(maskFile+"2",path.join(maskFile,"default")) if path.exists(nvidiaMaskFile): curNvidiaMask = open(nvidiaMaskFile,'r').read().strip() else: curNvidiaMask = "" maskNvidia = self.clVars.Get('os_nvidia_mask') if maskNvidia == curNvidiaMask: return True self.printByResult(True) self.printMessageForTest(_("Driver installation for %s")% self.clVars.Get('hr_video')) open(nvidiaMaskFile,'w').write(maskNvidia) try: envDict = {'PKGDIR':binPackages} envDict.update(os.environ) processEmerge = process('/usr/bin/emerge','-k','nvidia-drivers', envdict=envDict,stdout=PIPE,stderr=PIPE) res = processEmerge.success() except KeyboardInterrupt: self.setSignalInterrupt() os.unlink(nvidiaMaskFile) return False if not res: os.unlink(nvidiaMaskFile) return res def hideStdout(self): if not self.stdoutHide: self.stdoutHide = sys.stdout self.stderrHide = sys.stderr sys.stdout = StringIO() sys.stderr = StringIO() sys.stdout.fileno = self.stdoutHide.fileno sys.stderr.fileno = self.stderrHide.fileno def showStdout(self): if self.stdoutHide: sys.stdout = self.stdoutHide sys.stderr = self.stderrHide self.stdoutHide = None self.stderrHide = None def configureSystem(self): """configure current system""" configureMessage = _("Configure system") error = None keyInter = None try: try: # install this package self.installPackage() self.printMessageForTest(configureMessage) self.printByResult(self.applyTemplatesLive()) linuxShortname = self.clVars.Get('os_install_linux_shortname') # install desktop package if linuxShortname in ("CLD","CLS","CLDG","CLDX"): desktopLib = '/usr/lib/calculate-2.2/calculate-desktop/pym' if path.exists(desktopLib): sys.path.insert(0, path.abspath(desktopLib)) from cl_desktop import desktop self.printMessageForTest( _("Link calculate-desktop to package configuration")) self.hideStdout() objDesktop = desktop() objDesktop.createClVars() res = objDesktop.installProg() self.showStdout() self.printByResult(res) # install client package if linuxShortname in ("CLD","CLDG","CLDX"): clientLib = '/usr/lib/calculate-2.2/calculate-client/pym' if path.exists(clientLib): sys.path.insert(0, path.abspath(clientLib)) from cl_client import client self.printMessageForTest( _("Link calculate-client to package configuration")) objClient = client() objClient.createClVars() self.hideStdout() if hasattr(objClient,"updateEnvFiles") and \ objClient.updateEnvFiles(): objClient.clVars.flIniFile() res = objClient.installProg() self.showStdout() self.printByResult(res) objUsers = currentUsers() if self.clVars.Get('os_root_type') == "livecd": if not objUsers.hasUsers("guest"): self.printMessageForTest(_("Adding guest user")) self.printByResult(objUsers.addUsers("guest","guest")) pathGlModules = path.join(self.clVars.Get('cl_chroot_path'), 'usr/lib/opengl') self.printMessageForTest(_("Check the video driver")) self.printByResult(self.checkVideoDriver()) if path.exists(pathGlModules): self.printMessageForTest(_("Configure OpenGL")) self.printByResult(self.setupOpenGL()) except (InstallError,DistributiveError),e: error = e except Exception,e: error = "" for i in apply(traceback.format_exception, sys.exc_info()): error += i except KeyboardInterrupt: self.setSignalInterrupt() keyInter = True except KeyboardInterrupt: self.setSignalInterrupt() keyInter = True self.showStdout() if keyInter: if self.startMessage: self.printByResult(False) self.defaultPrint("\n") self.printWARNING(_("Interrupting the configuration")) error = _("Configuration manually interrupt") if self.startMessage: self.printByResult(False) 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 cleanInitrd(self): """Clean initrd from needless modules""" # get path to initrd and initrd-install in new system # (/boot/initramfs-...-install,/boot/initramfs-...) initrdPath = path.join(self.clVars.Get('cl_chroot_path'), 'boot',self.clVars.Get('os_install_initrd')) initrdInstallPath = path.join(self.clVars.Get('cl_chroot_path'), 'boot',self.clVars.Get('os_install_initrd_install')) # section which must contains equealent modules and kernel buildins importantSections = ['File systems','Pseudo filesystems', 'CDROM.*Filesystems', 'DOS.*Filesystems', 'SCSI Transport'] curConfig = dict(KernelConfig().getSectionParams(*importantSections)) if not self.clVars.Get('os_install_kernel_config'): copy2(initrdInstallPath,initrdPath); return True newConfig = KernelConfig( configFile= path.join(self.clVars.Get('cl_chroot_path'), 'boot',self.clVars.Get('os_install_kernel_config'))) newConfig = newConfig.getSectionParams(*importantSections) conflictOptions = filter(lambda x: x[1]=="M" and x[0] in curConfig and curConfig[x[0]]=="Y", newConfig) if conflictOptions: copy2(initrdInstallPath,initrdPath); return True return InitRamFs(initrdInstallPath).cleanInitRamFs(initrdPath) def afterCopyHDDinstall(self,targetDistr, addUsers, changePwdUsers, migrateUsers): """Action performed after distributive copy for hdd install""" # copy clt files from current system self.printMessageForTest(_("Coping clt templates to new system")) cltCpy = cltCopy(target=targetDistr.getDirectory()) for directory in self.clVars.Get('cl_template_clt_path'): cltCpy.performCopy(directory) self.printByResult(True) self.printMessageForTest(_("Coping configuration files to new system")) fileMask = r"/etc/udev/rules\.d/70-persistent-net\.rules" if self.clVars.Get('os_root_type') != "livecd": fileMask = "(%s|/etc/ssh/ssh_host_.*)"%fileMask fileCpy = otherfilesCopy(target=targetDistr.getDirectory(), reTest=fileMask) fileCpy.performCopy('/etc') self.printByResult(True) # join templates self.printMessageForTest(_("Updating config")) self.applyTemplates(targetDistr.getDirectory()) # mount bind mount points self.printByResult(True) # optimize initrd self.printMessageForTest(_("Creating new initrd file")) self.printByResult(self.cleanInitrd()) self.printMessageForTest(_("Post-install configuration")) targetDistr.postinstallMountBind() self.printByResult(True) # migrate users self.printMessageForTest(_("Migrate users")) objMigrate = migrate(targetDistr.getDirectory()) if not objMigrate.migrate(addUsers,changePwdUsers,migrateUsers): raise InstallError(_("Can not migrate users to new system")) self.printByResult(True) def installSystem(self, force=False, bootDisk=None, stdinReadPwd=False, builder=False, flagSpinner=True): """install System by current variable enviroment""" sourceDistr = None targetDistr = None error = None distrCopy = False 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'] self.printInfo() targetDistr = self.getTargetDistributive(rootPartdev, buildermode=builder, fileSystem=rootPartFileSystem, isFormat=rootPartIsFormat, systemId=rootPartSystemId) distRep = DistributiveRepository() minver = "10.8" instver = \ getTupleVersion(self.clVars.Get('os_install_linux_ver')) distName = self.clVars.Get('cl_image') if distName and instver < getTupleVersion(minver): self.printERROR( _("Installation is supported for system not less version" " %s")%minver) distName = "" if distName: # print info sourceDistr = distRep.getDistributiveByFile(distName) if not force: dialogMessage = _("Continue with the installation of \ the system") + " (yes/no)" try: dialogRes = dialogYesNo(dialogMessage) except KeyboardInterrupt: self.setSignalInterrupt() self.defaultPrint("\n") raise KeyboardInterrupt if dialogRes in (None,False): self.printERROR(_("Interrupting the installation")) return False # set Users passwords if self.clVars.Get('os_install_root_type') != "flash": changePwdUsers = \ self.generateHashRoot(stdinRead=stdinReadPwd) addUsers = self.generateHashUsers(stdinRead=stdinReadPwd) migrateUsers = self.getNamesMigrateUsers() mntpath = '/mnt' if not os.access(mntpath,os.W_OK): raise InstallError( _("Impossible create directory in '%s'")%mntpath) # cmd options self.printMessageForTest(_("Formating partitions")) targetDistr.performFormat() self.printByResult(True) # install distributive self.printMessageForTest( _("Unpacking system image into target")) self.defaultPrint(" ") self.lenStartMessage += 1 self.clVars.Get('os_grub_conf') # set spinner flag Distributive.flagSpinner = flagSpinner targetDistr.installFrom(sourceDistr) self.printByResult(True) if self.clVars.Get('os_install_root_type') != "flash": self.afterCopyHDDinstall(targetDistr, addUsers, changePwdUsers, migrateUsers) else: # join templates self.printMessageForTest( _("Configure of flash installation")) self.applyTemplatesFlash(targetDistr.getDirectory()) self.printByResult(True) self.closeClTemplate() # change boot config if self.clVars.Get('os_install_mbr'): self.printMessageForTest(_("Preparing system for reboot")) self.prepareBoot(targetDistr) self.printByResult(True) else: return False except (EOFError), e: error = e 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.setSignalInterrupt() self.printByResult(False) self.printWARNING(_("Interrupting the installation")) error = _("Installation manually interrupt") if error: self.printByResult(False) try: self.closeClTemplate() if sourceDistr and sourceDistr.childs: self.printMessageForTest(_("Releasing source distributive")) sourceDistr.close() self.printByResult(True) if targetDistr and targetDistr.childs: self.printMessageForTest(_("Unmount target system volume")) targetDistr.close() self.printByResult(True) except (InstallError,DistributiveError),e: error = "%s\n%s" % (str(error),_("Unmounting error")) except KeyboardInterrupt,e: self.setSignalInterrupt() pass if error: self.printByResult(False) 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 lang in self.clVars.Get('os_install_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 def installOverlay(self): return True #res,mes = runOsCommand('layman -l -N') #notempty = lambda x:x #if res == 0: # # map(lambda x:x[0], # filter(lambda x:x, # map(lambda x:filter(lambda x:x,x.split())[1:2], # mes))) # return True #else: # raise InstallError(_("Cann't get list layman overlays")) def installPackage(self): """Install this package. Convert Gentoo system to Calculate""" error = None self.printSUCCESS(_('Package installation')) try: self.printMessageForTest( _("Link calculate-install to package configuration")) self.printByResult(appendProgramToEnvFile(__app__, self.clVars), failMessage= _("Can not save '%(app)s' to %(path)s") %{'app':__app__, 'path':self.clVars.Get("cl_env_path")[0]}) 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.setSignalInterrupt() if self.startMessage: self.printByResult(False) self.defaultPrint("\n") error = _("Package installation manually interrupt") if self.startMessage: self.printByResult(False) if error: for line in filter(lambda x: x,str(error).split('\n')): self.printERROR(line) self.printERROR(_("Package installation failed")) return False return True def uninstallPackage(self): """Uninstall this package. Convert Calculate system to Gentoo""" error = None self.printSUCCESS(_('Package uninstallation')) try: self.printMessageForTest( _("Unlink calculate-install from package configuration")) self.printByResult(removeProgramToEnvFile(__app__, self.clVars), failMessage = _("Can not remove '%(app)s' to %(path)s")\ %{'app':__app__, 'path':self.clVars.Get("cl_env_path")[0]}) 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.setSignalInterrupt() if self.startMessage: self.printByResult(False) self.defaultPrint("\n") error = _("Package uninstallation manually interrupt") if self.startMessage: self.printByResult(False) if error: for line in filter(lambda x: x,str(error).split('\n')): self.printERROR(line) self.printERROR(_("Package uninstallation failed")) return False return True