You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-3-install/install/cl_install.py

2720 lines
126 KiB

#-*- 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.25"
__app__ = "calculate-install"
import os
import re
import sys
import traceback
from os import path
from StringIO import StringIO
from time import sleep
from subprocess import PIPE,STDOUT
from shutil import copy2
from calculate.lib.utils.files import (runOsCommand,pathJoin,scanDirectory,
process,listDirectory,STDOUT)
from calculate.lib.utils.common import (appendProgramToEnvFile,
removeProgramToEnvFile, getTupleVersion,
cmpVersion,getUserPassword,
getSupportArch, getInstalledVideo )
from calculate.lib.utils.device import (detectDeviceForPartition,
getUdevDeviceInfo, getLvmPartitions, refreshLVM,
refreshUdev)
from calculate.lib.cl_vars_share import varsShare
from calculate.lib import cl_overriding
from calculate.lib.utils import ip
from cl_kernel_utils import KernelConfig,InitRamFs
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
from calculate.lib.cl_fill import clLocale
from calculate.lib.cl_template import template
from calculate.lib.cl_datavars import DataVars
from calculate.lib.cl_print import color_print
from cl_distr import (PartitionDistributive,DistributiveRepository,
DistributiveError, ScratchPartitionDistributive,
MultiPartitions, Spinner, FlashDistributive, SignalInterrupt,
Distributive)
from calculate.lib.utils.text import tableReport
from calculate.lib.server.utils import dialogYesNo
from cl_migrate_users import migrate, currentUsers
from calculate.lib.encrypt import encrypt
from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_install',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, ('calculate.install.cl_vars_install',
'calculate.install.cl_fill_install'))
class convertDictOpt:
"""Convert dict install option"""
_defaultFS = "ext4"
_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"},
"btrfs":{"options":[],
"pair":{},
"incompatible":[],
"makefs":"/sbin/mkfs.btrfs"},
"nilfs2":{"options":[],
"pair":{},
"incompatible":[],
"makefs":"/sbin/mkfs.nilfs2"},
"jfs":{"options":[],
"pair":{},
"incompatible":[],
"makefs":"/sbin/mkfs.jfs"},
"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 = clVars.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(_("Duplicated 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(_("Duplicated 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 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
optProperties["srcMountPoint"] = \
path.normpath(optProperties["srcMountPoint"])
if "destMountPoint" in optProperties:
optProperties["destMountPoint"] = \
path.normpath(optProperties["destMountPoint"])
dictOptions = self.getDefaultOptBind().copy()
dictOptions.update(optProperties)
return dictOptions
optDevice = optProperties["dev"]
optProperties["dev"] = \
getUdevDeviceInfo(name=optDevice).get('DEVNAME',optDevice)
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(availableFS)&set(supportedFS)-excludeFS) \
and optMountPoint == '/':
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 option '%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(_("Failed to 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(_("Failed to 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)
cl_overriding.exit = installExit
cl_overriding.printERROR = overprintERROR
# refresh information about LVM
refreshLVM()
# refresh information about device in udevadm info
refreshUdev()
def setNoColor(self):
self.color = False
def initVars(self):
"""Primary initialization of variables"""
self.clVars = DataVarsInstall()
self.clVars.importInstall()
self.clVars.flIniFile()
def cmpInstallVersion(self):
"""Compare current and install version(build)
Return:
1 - new version above current and installed
0 - new version equal current or installed
-1 - new version less current or installed
-2 - installed versin above current and new
"""
rootdev = self.clVars.Get('os_install_root_dev')
d = DistributiveRepository()._getfromcontent(rootdev)
curver = self.clVars.Get('os_linux_ver')
curbuild = self.clVars.Get('os_linux_build')
curver = (getTupleVersion(curver),curbuild)
nextver = self.clVars.Get('os_install_linux_ver')
nextbuild = self.clVars.Get('os_install_linux_build')
nextver = (getTupleVersion(nextver),nextbuild)
curnextres = cmp(nextver,curver)
if d and "ver" in d:
installedver = (getTupleVersion(d["ver"]),
d["build"])
if installedver > curver:
instnextres = cmp(nextver,installedver)
if instnextres <= 0 and curnextres == 1:
return -2
return instnextres
return curnextres
def printAllPartitonsTable(self):
"""Print install report"""
title, headerList, dataList = self.generateTableAllPartitionData()
tableObj = tableReport("", headerList, dataList)
tableObj.printReport(False)
def printLocationTables(self):
"""Print install report"""
title, headerList, dataList = self.generateTableMountData()
tableObj = tableReport("", headerList, dataList)
tableObj.printReport(False)
title, headerList, dataList = self.generateTableBindData()
if dataList:
tableObj = tableReport(title, headerList, dataList)
tableObj.printReport(False)
def printNetworkTables(self):
"""Print install report"""
title, headerList, dataList = self.generateTableNetworkData()
tableObj = tableReport("", headerList, dataList)
tableObj.printReport(False)
def printRouteTables(self):
"""Print install report"""
title, headerList, dataList = self.generateTableRouteData()
tableObj = tableReport("", headerList, dataList)
tableObj.printReport(False)
def printInfo(self,update=False):
clGet = self.clVars.Get
installedSystem = "%s %s"%(clGet('os_linux_name'),
clGet('os_linux_ver'))
mbrDevice = self.clVars.Get('os_install_mbr')
if not mbrDevice in ("","off"):
syspath = getUdevDeviceInfo(name=mbrDevice).get('DEVPATH','')
if not syspath.startswith('/sys'):
syspath = pathJoin('/sys',syspath)
pathVendor = "%s/device/vendor"%syspath
pathModel = "%s/device/model"%syspath
if path.exists(pathVendor) and path.exists(pathModel):
addonMbrInfo = " (%s %s)"% \
(open(pathVendor,'r').read().strip(),
open(pathModel,'r').read().strip())
else:
addonMbrInfo = ""
mbrdisk = "%s%s"%(clGet('os_install_mbr'),addonMbrInfo)
else:
mbrdisk = _("will not be changed")
flash = clGet('os_install_root_type')=="flash"
usbhdd = clGet('os_install_root_type')=="usb-hdd"
hdd = clGet('os_install_root_type')=="hdd"
if not flash:
musers = ", ".join(set(clGet('cl_migrate_user'))-set(['root'])) \
or _("none")
else:
musers = _("none")
dnsNoValue = _("none")
dhcps = self.clVars.Get('os_install_net_dhcp_set')
if dhcps:
if dhcps[0] == "on":
dnsNoValue = _("DHCP")
self.printSUCCESS(_("Installation") + " Calculate Linux")
printData = [
[(_("System"),True),
(_("Computer name"),clGet('os_install_net_hostname'),not flash),
(_("Domain name"),clGet('os_install_net_domain'),not flash),
(_("Users"), musers,not flash),
(_("Installed system"),installedSystem,True)
],
[(_("Localization"),not flash),
(_("Language"),
clGet('os_install_locale_lang'),True),
(_("Keymap"),clGet('os_install_locale_xkbname'),True),
(_("Timezone"),clGet('os_install_clock_timezone'),True),
],
[(_("Network services"),hdd),
(_("Network manager"),clGet('os_install_net_conf'),True),
(_("PROXY"),
clGet('os_install_proxy') or _("none"),True),
(_("NTP"),clGet('os_install_ntp') or _("none"),True),
(_("DNS"),clGet('os_install_net_dns') or dnsNoValue,True)
],
[(_("Hardware"),True),
(_("Machine hardware name"),
clGet('os_install_arch_machine'),True),
(_("Number of processors"),clGet('hr_cpu_num'),hdd),
(_("Videocard"),clGet('hr_video_name'),hdd),
(_("{0} video driver").format("Xorg"),
clGet('os_install_x11_video_drv'),hdd),
(_("Screen resolution"),clGet('os_install_x11_resolution'),hdd)
],
[(_("Network devices"),not flash),
(self.printNetworkTables,None,True)
],
[(_("Routes"),not flash),
(self.printRouteTables,None,True)
],
[(_("Location"),True),
(_("Master boot record")+" (MBR)",mbrdisk,True),
(self.printLocationTables,None,True)
],
[(_("Perform pre-install checkups"),True)]
]
for section in printData:
sectionname,condition = section[0]
# skip section
if not (callable(condition) and condition() or \
not callable(condition) and condition ):
continue
self.defaultPrint("%s\n"%sectionname)
for label, data, cond in section[1:]:
if not (callable(cond) and cond() or \
not callable(cond) and cond ):
continue
if callable(label):
label()
else:
self.printSUCCESS(label+": %s"%data)
# preinstall 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 update:
cmpres = self.cmpInstallVersion()
image = self.clVars.Get('cl_image')
if image and ( not update or cmpres > 0):
deviceName = ""
if image.startswith('/dev'):
deviceImage = \
map(lambda x:x[1].rpartition(" ")[2],
filter(lambda x:x[0]==image,
self.clVars.zipVars("os_disk_dev","os_disk_content")))
if deviceImage:
if deviceImage[0] == "livecd":
deviceName = " " + _("on")+" CDROM (%s)"%image
else:
deviceName = " " + _("on")+" USB Flash (%s)"%image
self.printSUCCESS(_("An update found")+deviceName+": %s %s%s%s\n"%
(self.clVars.Get('os_install_linux_name'),
self.clVars.Get('os_install_linux_ver'),
subname,build))
else:
if update and cmpres == -2:
self.printWARNING(_("Update already installed."))
else:
self.printWARNING(_("No update available."))
def canInstallGrub2(self,target):
"""Check that system has grub2 in current and installed system"""
if self.clVars.Get('os_grub2_path'):
return bool(
filter(lambda x:x.startswith('grub-1.99'),
listDirectory('/var/db/pkg/sys-boot')))
return False
def prepareBoot(self,targetDistr):
"""Prepare system for boot"""
if self.clVars.Get('os_install_root_type') == "flash":
self.installSyslinuxBootloader(targetDistr)
else:
if self.canInstallGrub2(targetDistr):
self.installGrub2Bootloader(targetDistr)
else:
self.installLegacyGrubBootloader(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'))
mapPartPT = dict(self.clVars.zipVars("os_disk_dev","os_disk_table"))
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 applyTemplatesStartup(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 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_chroot_grub","/", 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,grubDirectory):
"""Apply templates for root of system."""
self.clVars.Set("cl_chroot_path",directory, True)
self.clVars.Set("cl_chroot_grub",grubDirectory, 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 checkDuplicate(self,datalist,name,key=lambda x:x):
"""Check on duplicate and print error"""
keydata = map(key,datalist)
dupKey = set(filter(lambda x:keydata.count(x)>1, keydata))
if dupKey:
self.printERROR(_("Duplicated {keyname}: {keylist}").format(
keyname=name,keylist=",".join(dupKey)))
return False
return True
def setVarList(self,varsList,matrix):
"""Set matrix to vars"""
if not matrix:
map(lambda x:self.clVars.Set(x,[],True),varsList)
else:
map(lambda x:self.clVars.Set(x[0],list(x[1]),True),
zip(varsList,zip(*matrix)))
def setNetwork(self,ipaddrs,dhcps,routes):
"""Set network configuration"""
def changeIpData(ipdata):
iface,ipaddr,cidr,dhcpset = ipdata
if iface in dhcps:
if dhcpset == "off":
invalidRouteIface.append(iface)
dhcpset = "on"
cidr = ""
ipaddr = ""
elif iface in dictIpAddr:
newipaddr,op,newcidr = dictIpAddr[iface].partition('/')
if dhcpset == "on" or newipaddr != ipaddr or newcidr != cidr:
invalidRouteIface.append(iface)
ipaddr,cidr = newipaddr,newcidr
dhcpset = "off"
return (iface,ipaddr,cidr,dhcpset)
def removeInvalidRoutes(routedata):
"""Remove route for device with new ip"""
network,gw,dev,src = routedata
if dev in invalidRouteIface:
return False
return True
def removeSpecifiedRoutes(routedata):
"""Remove route for user specified"""
network,gw,dev,src = routedata
if network in specifedNet:
return False
return True
def specifedRoutes(routes,ipAddrs,routedata):
NET,GW,DEV,SRC=0,1,2,3
nets = filter(lambda net:net != "default",
map(lambda x:x[NET],routes)+map(lambda x:x[NET],routedata))
routes = filter(lambda x:x[GW] or x[SRC],routes)
wrongGws = map(lambda x:x[GW],
filter(lambda x:not ip.isIpInNet(x[GW],
*(set(nets)-set([x[NET]]))),
filter(lambda x:x[GW],
routes)))
if wrongGws:
raise InstallError(_("Gateways %s is unreachable")%
(",".join(wrongGws)))
wrongIps = map(lambda x:x[SRC],
filter(lambda x:not x[SRC] in ipAddrs,
filter(lambda x:x[SRC],routes)))
if wrongIps:
raise InstallError(_("Wrong ip addresse %s in source IP")%
(",".join(wrongIps)))
newroutes = []
for network,gw,dev,src in routedata+routes:
if not dev:
gwnetwork = ip.isIpInNet(gw,*nets)[0]
dev = filter(lambda x:x[NET]==gwnetwork,
routedata+newroutes)
if not dev:
raise InstallError(
_("Failed to determine the device for network %s")%
network)
dev = dev[0][DEV]
if not gw and not src:
continue
newroutes.append((network,gw,dev,src))
return newroutes
def standardRoutes(ipMatrix,needDev):
IFACE,IP,CIDR,DHCP = 0,1,2,3
return map(lambda x:(ip.getIpNet(x[IP],cidr=x[CIDR]),
"",x[IFACE],x[IP]),
filter(lambda x:x[DHCP] =="off" and x[IFACE] in needDev,
ipMatrix))
# check interfaces
getVar = self.clVars.Get
interfaces = getVar('os_install_net_interfaces')
if interfaces:
defaultIface = interfaces[0]
else:
defaultIface = ""
ipaddrs = map(lambda x: x if len(x)==2 else (defaultIface,x[0]),
ipaddrs)
specifiedIface = dhcps + map(lambda x:x[0],ipaddrs)
routeIface = filter(lambda x:x,
map(lambda x:x[2],filter(lambda x:len(x)>2,routes)))
wrongIface = set(specifiedIface+routeIface)-set(interfaces)
# check correct iface
if wrongIface:
self.printERROR(_("Wrong interface: %s")%",".join(wrongIface))
return False
# check dup iface
if not self.checkDuplicate(specifiedIface,_("interfaces")):
return False
# check dup ip
if not self.checkDuplicate(ipaddrs,_("addresses"),key=lambda x:x[1]):
return False
dictIpAddr = dict(ipaddrs)
# set user data to variables
ipVars = map(lambda x:'os_install_net_%s'%x,
('interfaces', 'ip', 'cidr', 'dhcp_set'))
invalidRouteIface = []
self.setVarList(ipVars, map(changeIpData, self.clVars.zipVars(*ipVars)))
specifedNet = map(lambda x:x[0],routes)
routeVars = map(lambda x:'os_install_net_route_%s'%x,
('network', 'gw', 'dev', 'src'))
try:
self.setVarList(routeVars,
specifedRoutes(routes,getVar('os_install_net_ip'),
filter(removeSpecifiedRoutes,
standardRoutes(self.clVars.zipVars(*ipVars),invalidRouteIface)+
filter(removeInvalidRoutes,
self.clVars.zipVars(*routeVars)))))
except InstallError,e:
self.printERROR(str(e))
return False
# check dup nets
if not self.checkDuplicate(routes,_("networks"),key=lambda x:x[0]):
return False
return True
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 does not support multipartition install"))
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(
_("Unable to use the extended partition %s for installation")%
usingExtPart[0])
return False
# detect using CDROM disks
cdromPartitions = map(lambda x: x[1],
filter(lambda x: "cdrom" in x[0],
zip(self.clVars.Get('os_disk_type'),
self.clVars.Get('os_disk_dev'))))
usingCdromPart = list(set(usedDevices)&set(cdromPartitions))
if usingCdromPart:
self.printERROR(_("Unable to use CDROM %s for installation")%
usingCdromPart[0])
return False
# detect using RAID member disks
raidMemberData = filter(lambda x: "raidmember" in x[0],
zip(self.clVars.Get('os_disk_type'),
self.clVars.Get('os_disk_dev')))
raidMemberPartitions = map(lambda x:x[1],raidMemberData)
usingRaidMemberPart = list(set(usedDevices)&set(raidMemberPartitions))
if usingRaidMemberPart:
raidMemberData = filter(lambda x:x[1] in usingRaidMemberPart,
raidMemberData)[0][0]
raidMemberData = raidMemberData.rpartition("raidmember(")[2]
raidMemberData = raidMemberData.partition(")")[0]
self.printERROR(_("Unable to use active {typepart} member {part} "
"for installation").format(
typepart="RAID",part=usingRaidMemberPart[0]))
self.printERROR(
_("To use this partition, you have to stop RAID %s")%
raidMemberData)
self.printERROR(" mdadm -S %s"%raidMemberData)
return False
# detect using LVM member disks
lvmMemberData = filter(lambda x: "lvmmember" in x[0],
zip(self.clVars.Get('os_disk_type'),
self.clVars.Get('os_disk_dev')))
lvmMemberPartitions = map(lambda x:x[1],lvmMemberData)
usingLvmMemberPart = list(set(usedDevices)&set(lvmMemberPartitions))
if usingLvmMemberPart:
lvmMemberData = filter(lambda x:x[1] in usingLvmMemberPart[0],
lvmMemberData)[0][0]
lvmMemberData = lvmMemberData.rpartition("lvmmember(")[2]
lvmMemberData = lvmMemberData.partition(")")[0]
prop = getUdevDeviceInfo(name=lvmMemberData)
vgName = prop.get('DM_VG_NAME','')
self.printERROR(_("Unable to use active {typepart} member {part} "
"for installation").format(
typepart="LVM",part=usingLvmMemberPart[0]))
self.printERROR(
_("To use this partition, you have to remove LVM %s")%
lvmMemberData)
self.printERROR(" vgremove %s"%vgName)
self.printERROR(" pvremove %s"%usingLvmMemberPart[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 used "
"for binding '%(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
rootdevs = map(lambda x:x['dev'],
filter(lambda x:"mountPoint" in x and \
"dev" in x and \
x['mountPoint']=='/',
listDisks))
if rootdevs:
self.clVars.Set('os_install_root_dev',rootdevs[0],True)
rootType = self.clVars.Get('os_install_root_type')
curRootType = self.clVars.Get('os_root_type')
def clearParam(data,isswap):
if rootType == 'usb-hdd' and curRootType != "usb-hdd":
return ""
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
DEV,MOUNT,FS,OPTS = 0,1,2,3
devMount = dict(map(lambda x:(x[DEV],
{'mountPoint':clearParam(x[MOUNT],x[MOUNT]),
'fileSystem':x[FS],
'options':clearParam(x[OPTS],x[MOUNT]),
'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 the 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(_("The root partition must be specified"))
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 supported for "
"multipartition install"))
return False
if filter(lambda x:x['dev']!="none",listSwaps):
self.printERROR(
_("Installation to flash disk is not "
"supported for swap disks"))
return False
if builderMode:
self.printERROR(
_("Installation to flash disk is not supported"
" in 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)))
if not self.clVars.Get('os_grub2_path'):
if not self.checkForLegacyGrub():
return False
else:
if not self.checkForGrub2():
return False
return True
def checkForGrub2(self):
"""Check current disk configuration for installation for install
GRUB2"""
bootDiskType = self.varSelect("os_disk_type",
where="os_install_disk_mount", eq="/boot")
rootDiskType = self.varSelect("os_disk_type",
where="os_install_disk_mount", eq="/")
grubDiskType = bootDiskType or rootDiskType
if "lvm-raid" in grubDiskType:
self.printERROR(
_("Grub does not support booting from a RAID assembled from LVM.")
+ " " +
_("Try to use a separate /boot partition"))
return False
if grubDiskType.count("raid")>1:
self.printERROR(
_("Grub does not support booting from a RAID assembled "
"from another RAID.")
+ " " +
_("Try to use a separate /boot partition"))
return False
return True
def checkForLegacyGrub(self):
"""Check current disk configuration for installation for install
legacy grub"""
bootDiskType = self.varSelect("os_disk_type",
where="os_install_disk_mount", eq="/boot")
rootDiskType = self.varSelect("os_disk_type",
where="os_install_disk_mount", eq="/")
bootDiskFormat = self.varSelect("os_install_disk_format",
where="os_install_disk_mount", eq="/boot")
rootDiskFormat = self.varSelect("os_install_disk_format",
where="os_install_disk_mount", eq="/")
bootDiskType = bootDiskType or rootDiskType
bootDiskFormat = bootDiskFormat or rootDiskFormat
if "lvm" in bootDiskType or "raid" in bootDiskType:
self.printERROR(
_("Legacy grub does not support boot from raid or lvm "
"without separate /boot partition"))
return False
if bootDiskFormat in ("btrfs","nilfs2"):
self.printERROR(
_("Legacy grub does not support booting from %s without "
"separate /boot partition")%bootDiskFormat)
return False
return True
def setUsers(self,listUsers,autologinUser):
"""Set users data (migration)"""
if autologinUser == "none":
autologinUser = ""
if autologinUser or autologinUser == "":
self.clVars.Set('cl_autologin', autologinUser, force=True)
else:
autologinUser = self.clVars.Get('cl_autologin')
autologinUser = [autologinUser] if autologinUser else []
listUsers = listUsers or []
if listUsers or autologinUser:
migrateUsers = list(set(listUsers+autologinUser))
migrateUsers.sort()
migrateUsers = ["root"] + filter(lambda x: x!="root", migrateUsers)
self.clVars.Set('cl_migrate_user', migrateUsers, force=True)
return True
def setBR(self, mbrDisk):
"""Set boot record on disk by param or get from variables"""
bootDiskGrub = ""
if mbrDisk == "off":
self.clVars.Set('os_install_mbr',"",force=True)
return True
elif mbrDisk:
if filter(lambda x: x == mbrDisk,
self.clVars.Get('os_device_dev')):
self.clVars.Set('os_install_mbr', mbrDisk, force=True)
else:
self.printERROR(_("Failed to find 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,
autologinUser, brDisk):
"""Set install options (set users, disks and boot record"""
try:
if self.setUsers(listUsers,autologinUser) and \
self.setDisks(listDisks,listBinds,listSwaps) and \
self.setBR(brDisk):
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):
"""TODO: don't work with GPT. Don't work must be rewrite!!!!!"""
reActive = re.compile('^%s\s*[*]'%partition)
device = filter(lambda x:x in partition,
self.clVars.Get('os_device_dev'))
if not device:
raise DistributiveError(_("Failed to find the parent device"))
device = device[0]
fdiskProcess = process("/sbin/fdisk","-l",device)
if fdiskProcess.failed():
raise DistributiveError(_("Failed to 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", 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",device)):
return True
raise DistributiveError(_("Failed to set the 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=%s"%self.clVars.Get('os_install_mbr'),
stderr=STDOUT)
if ddProcess.failed():
raise DistributiveError(
_("Failed to write the 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(_("Failed to install syslinux\n%s")%
syslinuxProcess.read())
# is partition active
return self.setActivePartition(self.clVars.Get('os_install_root_dev'))
def varSelect(self,selField,where="os_disk_dev",eq=""):
"""Select value from os_disk/device matrix"""
res = filter(lambda x: x[1] == eq,
zip(self.clVars.Get(selField),
self.clVars.Get(where))) or\
[("","")]
return res[0][0]
def getPartitionForParted(self,partition):
"""Get partition info for parted exectution"""
# get disk num and partitin num
bootMap = \
self.varSelect("os_disk_grub",where="os_disk_dev",eq=partition)
# check valid numbers
deviceNumber,op,partitionNumber = bootMap.partition(',')
if not deviceNumber.isdigit() or \
not partitionNumber.isdigit():
return (False,False)
# get partition number
partitionNumber = int(partitionNumber)+1
# get device name
deviceName = self.varSelect("os_device_dev",where="os_device_map",
eq=int(deviceNumber))
if deviceName:
return (deviceName,partitionNumber)
return (False,False)
def setBiosGrubForBootPartition(self):
"""Set bios_grub flag for boot partition in gpt (WRONG)"""
for bootPath in ("/boot","/"):
# get grub disk by mount point
bootPart = self.varSelect(
"os_disk_part",where="os_install_disk_mount",eq=bootPath)
if bootPart:
if bootPart == "gpt":
bootPart = self.varSelect(
"os_disk_dev",where="os_install_disk_mount",eq=bootPath)
deviceName,partitionNumber = \
self.getPartitionForParted(bootPart)
cmdParted = varsShare().getProgPath('/usr/sbin/parted')
if not cmdParted:
return False
partedProcess = process(cmdParted,deviceName,
"set",str(partitionNumber),"bios_grub","on")
return partedProcess.success()
return True
return False
def installGrub2Bootloader(self,target):
"""Install grub2 boot loader"""
cmdGrubInstall = self.clVars.Get('os_grub2_path')
#if not self.setBiosGrubForBootPartition():
# raise DistributiveError(
# _("Failed to set bios_grub flag for the boot partition"))
if not cmdGrubInstall:
raise DistributiveError(_("Failed to install the bootloader"))
mbrDisk = self.clVars.Get('os_install_mbr')
process("sync").success()
grubProcess = process(cmdGrubInstall,
"--boot-directory=%s"%target.getBootDirectory(),
mbrDisk, "-f", stderr=STDOUT,envdict=os.environ)
if grubProcess.failed():
raise DistributiveError(_("Failed to install the bootloader"))
def installLegacyGrubBootloader(self,target):
"""Install boot loader
Perform grub installation to disk, which has root partition
"""
cmdGrub = varsShare().getProgPath('/sbin/grub')
if not cmdGrub:
raise DistributiveError(_("Failed to install the bootloader"))
grubProcess = process(cmdGrub,
"--device-map=%s/boot/grub/device.map"%target.getDirectory(),
"--batch",stderr=STDOUT)
for bootPath in ("/boot","/"):
# get grub disk by mount point
bootDisk = self.varSelect(
"os_disk_grub",where="os_install_disk_mount",eq=bootPath)
if bootDisk:
break
mbrDisk = self.clVars.Get('os_install_mbr')
mbrDiskNum = self.varSelect(
"os_device_map",where="os_device_dev",eq=mbrDisk)
if not mbrDiskNum and mbrDiskNum != 0:
raise DistributiveError(_("Failed to determine mbr"))
for line in ("root (hd%s)"%bootDisk,
"setup (hd%d)"%mbrDiskNum,
"quit"):
grubProcess.write("%s\n"%line)
if grubProcess.failed():
raise DistributiveError(_("Failed to install the bootloader"))
def convertTypeToScheme(self,data):
"""Convert os_disk_type to human readable names"""
if type(data) == tuple:
diskScheme, driveType = data
else:
diskScheme, driveType = data,""
res = ""
if diskScheme.endswith("raid-lvm"):
return _("LVM on RAID")
elif "disk-partition" == diskScheme and driveType == "flash":
return _("Partition on flash")
elif "disk-partition" == diskScheme and driveType == "usb-hdd":
return _("Partition on USB-HDD")
elif "disk-partition" == diskScheme:
return _("Partition on disk")
elif "raid-partition" == diskScheme:
return _("Partition on RAID")
elif "raidmember" in diskScheme:
diskScheme = diskScheme.rpartition("raidmember(")[2]
diskScheme = diskScheme.partition(")")[0]
return _("RAID %s member")%diskScheme
elif "lvmmember" in diskScheme:
lvms = []
while "lvmmember" in diskScheme:
diskScheme,op,data = diskScheme.rpartition("lvmmember(")
lvms.append(data.partition(")")[0])
return _("LVM %s member")%",".join(lvms)
elif "disk" == diskScheme:
return _("Disk without partitions")
elif "lvm" in diskScheme:
return _("LVM")
elif "raid" in diskScheme:
return _("RAID")
elif "cdrom" in diskScheme:
return _("CDROM")
else:
return _("Partition")
def generateTableAllPartitionData(self):
"""Generate table for all partitions"""
title = _("Available partitions")
headerList = [_("Size"),_("Device"),_("Label"),_("Mount point"),
_("File system"), _("Type"),_("OS")]
deviceHash = self.clVars.Get('os_device_hash')
diskHash = self.clVars.Get('os_disk_hash')
getTypeByDevice = lambda x: \
deviceHash.get(diskHash[x].get('parent',{}),{}).get('type','')
return title, headerList, zip(self.clVars.Get('os_disk_size'),
self.clVars.Get('os_disk_dev'),
self.clVars.Get('os_disk_name'),
self.clVars.Get('os_disk_mount'),
self.clVars.Get('os_disk_format'),
map(self.convertTypeToScheme,
zip(self.clVars.Get('os_disk_type'),
map(getTypeByDevice,self.clVars.Get('os_disk_dev')))),
self.clVars.Get('os_disk_content'))
def generateTableMountData(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,
map(lambda x:x[0] or x[1],
zip(self.clVars.Get('os_disk_part'),
map(self.convertTypeToScheme,
self.clVars.Get('os_disk_type')))),
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 generateTableNetworkData(self):
"""Get bind data for print table"""
def ipInformation(listIpMaskDhcp):
ipaddr,cidr,dhcp = listIpMaskDhcp
if dhcp == "on":
return _("DHCP")
elif ipaddr:
return "{ip}/{cidr}".format(ip=ipaddr,cidr=cidr)
else:
return _("Off")
clGet = self.clVars.Get
title = _("Network devices")
headerList = [_("Device"),_("Name"),_("MAC address"),_("IP address")]
return title, headerList, zip(clGet('os_install_net_interfaces'),
clGet('os_install_net_name'),
clGet('os_install_net_mac'),
map(ipInformation,
zip(clGet('os_install_net_ip'),
clGet('os_install_net_cidr'),
clGet('os_install_net_dhcp_set'))))
def generateTableRouteData(self):
"""Get bind data for print table"""
clGet = self.clVars.Get
title = _("Routes")
headerList = [_("Device"),_("Network"),_("Gateway"),_("Source IP")]
return title, headerList, zip(clGet('os_install_net_route_dev'),
clGet('os_install_net_route_network'),
clGet('os_install_net_route_gw'),
clGet('os_install_net_route_src')) + \
map(lambda x:(x[0],_("DHCP"),_("DHCP"),_("DHCP")),
filter(lambda x:x[1]=='on',zip(clGet('os_install_net_interfaces'),
clGet('os_install_net_dhcp_set'))))
def getPwdHashUser(self, userName, stdinRead=False):
if stdinRead:
try:
userPwd = sys.stdin.readline().rstrip()
except EOFError:
raise KeyboardInterrupt()
else:
cl_overriding.printSUCCESS(_("Enter the 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(_("Failed 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,autologin):
"""configuring the current system"""
configureMessage = _("Configure the system")
error = None
keyInter = None
try:
try:
if autologin:
objUsers = currentUsers()
if not objUsers.hasUsers(autologin):
self.printERROR(_("User %s does not exist")%autologin)
else:
self.setUsers([],autologin)
# install this package
self.installPackage()
self.printMessageForTest(configureMessage)
self.printByResult(self.applyTemplatesStartup())
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(
_("Enable calculate-desktop "
"for 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(
_("Enable calculate-client for 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)
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())
# if change video driver, then restore initramfs
installDrv = self.clVars.Get('os_install_x11_video_drv')
if self.clVars.Get('os_x11_video_drv') != installDrv:
initrdPath = path.join('/boot',
self.clVars.Get('os_install_initrd'))
initrdInstallPath = path.join('/boot',
self.clVars.Get('os_install_initrd_install'))
needMod = {'radeon':'radeon',
'intel':'i915',
'nouveau':'nouveau'}.get(installDrv,'uvesafb')
if not InitRamFs(initrdPath).isModuleInside(needMod):
self.printMessageForTest(_("Restoring initramfs"))
self.printByResult(InitRamFs(initrdInstallPath)\
.cleanInitRamFs(initrdPath))
oldXdrv = self.clVars.Get('os_x11_video_drv')
newXdrv = self.clVars.Get('os_install_x11_video_drv')
if oldXdrv != newXdrv:
kmsDrv = ("radeon","i915","intel","nouveau","ati")
self.defaultPrint("\n")
if oldXdrv in kmsDrv or newXdrv in kmsDrv:
self.defaultPrint(
_("To apply the changes, reboot the system")
+".\n")
else:
self.defaultPrint(
_("To apply the changes, restart the X server")
+".\n")
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(_("System configuration interrupted"))
error = _("Configuration manually interrupted")
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-...)
chrootPath = path.join(self.clVars.Get('cl_chroot_path'),'boot')
initrdPath = path.join(chrootPath,self.clVars.Get('os_install_initrd'))
initrdInstallPath = path.join(chrootPath,
self.clVars.Get('os_install_initrd_install'))
copy2(initrdInstallPath,initrdPath);
return True
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 the 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 the 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)
# optimize initrd
self.clVars.Set("cl_chroot_path",targetDistr.getDirectory(), True)
self.printMessageForTest(_("Creating a new initrd file"))
self.printByResult(self.cleanInitrd())
# join templates
self.printMessageForTest(_("Updating configuration"))
self.applyTemplates(targetDistr.getDirectory(),
targetDistr.getBootDirectory()[:-4])
# mount bind mount points
self.printByResult(True)
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(_("Failed to migrate users to the new system"))
self.printByResult(True)
def checkCorrectBootRecordDisk(self):
"""Check boot record disk"""
mbr = self.clVars.Get('os_install_mbr')
if mbr == "off" or mbr == "":
return True
tableOnBootDisk = self.varSelect('os_device_table',
where="os_device_dev",eq=mbr)
if not tableOnBootDisk:
self.printERROR(_("Disk '%s' without partition table "
"contains no boot record")%mbr)
return False
return True
def installSystem(self, force=False, bootDisk=None, stdinReadPwd=False,
builder=False, flagSpinner=True, update=False):
"""install System by current variable enviroment"""
sourceDistr = None
targetDistr = None
error = None
distrCopy = False
if not self.checkCorrectBootRecordDisk():
return 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(update=update)
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 version %s or higher")%minver)
distName = ""
if distName and (not update or self.cmpInstallVersion()>0):
# 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(_("Installation interrupted"))
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(
_("Enable to create the directory in '%s'")%mntpath)
# cmd options
self.printMessageForTest(_("Formating partitions"))
targetDistr.performFormat()
self.printByResult(True)
# install distributive
self.printMessageForTest(
_("Unpacking the 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 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(_("Installation interrupted"))
error = _("Installation manually interrupted")
if error:
self.printByResult(False)
try:
self.closeClTemplate()
if sourceDistr and sourceDistr.childs:
self.printMessageForTest(_("Releasing the source distribution"))
sourceDistr.close()
self.printByResult(True)
if targetDistr and targetDistr.childs:
self.printMessageForTest(_("Unmount the 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 installed"))
try:
self.printMessageForTest(
_("Enable calculate-install for package configuration"))
self.printByResult(appendProgramToEnvFile(__app__, self.clVars),
failMessage= _("Failed to 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 interrupted manually")
if self.startMessage:
self.printByResult(False)
if error:
for line in filter(lambda x: x,str(error).split('\n')):
self.printERROR(line)
self.printERROR(_("Failed to install the package"))
return False
return True
def uninstallPackage(self):
"""Uninstall this package. Convert Calculate system to Gentoo"""
error = None
self.printSUCCESS(_('Package uninstallation'))
try:
self.printMessageForTest(
_("Disable calculate-install for package configuration"))
self.printByResult(removeProgramToEnvFile(__app__, self.clVars),
failMessage = _("Failed to 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 interrupted manually")
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
def setIso(self,isoimage):
"""Set iso image for installation"""
imageData = DistributiveRepository()._getfromcontent(isoimage)
if "name" in imageData and imageData.get('build','') and \
"march" in imageData:
self.clVars.Set('os_install_arch_machine',
imageData['march'],True)
self.clVars.Set('os_install_linux_build',
imageData['build'],True)
self.clVars.Set('os_install_linux_ver',
imageData['ver'],True)
self.setLinuxName(imageData['name'].upper())
self.clVars.Set('cl_image',isoimage,True)
return True
else:
self.printERROR(_("Wrong image file"))
return False
def setVideo(self,video,startup=False):
"""Set video driver"""
if startup:
if not video in getInstalledVideo(prefix="/") and \
not video in ("auto","other"):
self.printERROR(_("%s videodriver is unavailable")%video)
if video == "nvidia":
self.printERROR(_("Install %s driver with:")%"NVidia")
self.printERROR(" emerge x11-drivers/nvidia-drivers")
if video == "fglrx":
self.printERROR(_("Install %s driver with:")%"ATI")
self.printERROR(" emerge x11-drivers/ati-drivers")
return False
self.clVars.Set('os_install_x11_video_drv',video,force=True)
return True
def setTimezone(self,timezone):
"""Set timezone"""
if not path.exists(path.join("/usr/share/zoneinfo",timezone)) or \
timezone.startswith('/usr/share/zoneinfo'):
self.printERROR(_("%s timezone is wrong")%timezone)
return False
else:
self.clVars.Set('os_install_clock_timezone',timezone,force=True)
return True
def setArchitecture(self,march):
"""Set architecture by march (support auto keyword)"""
if march == "auto":
march = getSupportArch()[-1]
self.clVars.Set('os_install_arch_machine', march, True)