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/pym/install/variables/system.py

866 lines
26 KiB

9 years ago
# -*- coding: utf-8 -*-
# Copyright 2008-2016 Mir Calculate. 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.
import os
import sys
import re
from os import path
9 years ago
from calculate.lib.datavars import (Variable, VariableError, ReadonlyVariable,
TableVariable, PasswordError,
DataVarsError, VariableInterface)
from calculate.install.fs_manager import FileSystemManager
9 years ago
from calculate.lib.utils.files import (readFile, getProgPath, process,
readLinesFile)
from calculate.lib.utils.common import getPasswdUsers, getUserGroups, getGroups, \
CmdlineParams
9 years ago
from calculate.lib.utils.common import getValueFromConfig, getValueFromCmdLine
from calculate.lib.utils.common import getUserPrimaryGroup
from calculate.lib.utils.portage import isPkgInstalled
12 years ago
from calculate.lib.utils.device import getUdevDeviceInfo
from crypt import crypt
from autopartition import SchemeOpt, SchemeDevices
from calculate.lib.encrypt import encrypt
9 years ago
import calculate.lib.cl_ini_parser as cl_ini_parser
9 years ago
from calculate.lib.cl_lang import setLocalTranslate, _
9 years ago
setLocalTranslate('cl_install3', sys.modules[__name__])
9 years ago
class UserHelper(VariableInterface):
"""
Locale variables not using for flash installation
"""
xorg_need = False
def uncompatible(self):
"""
User setting up unavailable for flash installation
"""
if self.Get('os_install_root_type') == 'flash':
12 years ago
return _("User configuration unavailable for Flash install")
if self.Get('os_install_x11_server_set') == 'off' and self.xorg_need:
return _("Autologin is available for Xorg sessions only")
return ""
9 years ago
class VariableOsInstallScratch(ReadonlyVariable):
"""
Install system in scratch mode
"""
9 years ago
type = "bool"
opt = ['--build']
def get(self):
# for installation default - normal system
if self.Get('cl_action') == 'system':
return "off"
else:
return self.Get('os_scratch')
9 years ago
class VariableOsFormatType(ReadonlyVariable):
"""
Filesystem format support by calcualte-install
"""
type = "list"
def get(self):
"""Filesystem format support by calcualte-install"""
return FileSystemManager.supportFS.keys()
9 years ago
class VariableOsFormatUse(ReadonlyVariable):
"""
Avialable format by mkfs utility
"""
type = "list"
# (on or off) autoupdate config from install program
9 years ago
cl_autoupdate_set = {
'type': "bool",
'value': "off"}
9 years ago
def checkFunc(self, fs):
if "format" in FileSystemManager.supportFS[fs] and \
9 years ago
path.exists(FileSystemManager.supportFS[fs]["format"]):
return "yes"
return "no"
def get(self):
return map(self.checkFunc, self.Get('os_format_type'))
9 years ago
class VariableClMigrateRootPwd(UserHelper, Variable):
"""
Root password
"""
type = "password"
opt = ["--root-password"]
metavalue = 'PASSWORD'
untrusted = True
def init(self):
12 years ago
self.help = _("specify the root password")
self.label = _("Root password")
def get(self):
9 years ago
rootPasswd = map(lambda x: x[1],
filter("root".__eq__,
map(lambda x: x.split(':')[0:2],
readLinesFile('/etc/shadow'))))
if rootPasswd:
rootPasswd = rootPasswd[0]
else:
rootPasswd = ""
# if root password is "root"
if rootPasswd:
salt = "".join(rootPasswd.rpartition("$")[:1])
if salt and crypt("root", salt) == rootPasswd:
rootPasswd = ""
return rootPasswd or ""
9 years ago
def set(self, value):
"""
Encrypt password
"""
reCheck = re.compile("^\$[^$]+\$[^$]+\$.*$")
encryptObj = encrypt()
if reCheck.match(value) or not value:
return value
else:
return encryptObj.getHashPasswd(value, "shadow_ssha256")
9 years ago
def check(self, value):
if not value:
9 years ago
raise PasswordError(_("Password for user %s missing") % "root")
9 years ago
class VariableClInstallHomeCryptSet(UserHelper, Variable):
type = 'bool'
9 years ago
opt = ["--crypt-home", "-C"]
untrusted = True
def init(self):
self.help = _("encrypt user profiles")
self.label = _("Encrypt user profiles")
def get(self):
return ("off" if self.Get('cl_autologin')
else self.Get('cl_home_crypt_set'))
9 years ago
def check(self, value):
if value == "on" and self.Get('cl_autologin'):
raise VariableError(
_("User profile encryption is uncompatible with autologin"))
9 years ago
class VariableClMigrateData(UserHelper, TableVariable):
"""
User migrate data table
"""
type = 'table'
9 years ago
opt = ["--user", "-u"]
metavalue = 'USER[:GROUPS]'
9 years ago
source = ['cl_migrate_user', 'cl_migrate_user_groups',
'cl_migrate_user_pwd']
untrusted = True
def init(self):
self.help = _("add a user to the installed system")
self.label = _("Migrating users")
9 years ago
class VariableClMigrateDataBrief(UserHelper, TableVariable):
"""
User migrate data table for brief view
"""
9 years ago
source = ['cl_migrate_user', 'cl_migrate_user_groups']
def init(self):
self.label = _("Migrating users")
9 years ago
class VariableClMigrateUser(UserHelper, Variable):
"""
Migrate users list
"""
type = 'list'
def init(self):
self.label = _("Users")
def get(self):
"""
Migrating users (users above 1000 uid)
"""
9 years ago
return filter("root".__ne__, getPasswdUsers())
9 years ago
class VariableClMigrateUserGroups(UserHelper, Variable):
"""
Migrate users groups
"""
type = 'choice-list-list'
9 years ago
defaultGroupList = ["users", "wheel", "audio", "cdrom", "video",
"cdrw", "usb", "plugdev", "games", "lp", "scanner",
"uucp"]
def getDefaultGroups(self):
9 years ago
return list(set(self.defaultGroupList) & set(getGroups()))
def init(self):
self.label = _("Groups")
9 years ago
def set(self, value):
value = map(lambda x: (filter(None, x) if x and any(x)
else self.getDefaultGroups()),
9 years ago
value)
return value
def getPrimaryGroup(self, username):
pg = getUserPrimaryGroup(username)
if pg:
return [pg]
return []
def get(self):
"""
User groups
"""
passwdList = getPasswdUsers()
return map(lambda x: (self.getPrimaryGroup(x) +
(getUserGroups(x)
if x in passwdList else
self.getDefaultGroups())),
9 years ago
self.Get('cl_migrate_user'))
def choice(self):
"""
Available groups
"""
return [("", _("Default"))] + [(x, x) for x in getGroups()]
9 years ago
class VariableClMigrateUserPwd(UserHelper, Variable):
"""
Migrate users who need to change passwords
"""
type = 'password-list'
def init(self):
self.label = _("Password")
def get(self):
"""
Migrating users passwords
"""
retList = []
fileName = "/etc/shadow"
if os.access(fileName, os.R_OK):
migrateusers = self.Get("cl_migrate_user")
if migrateusers:
9 years ago
lenData = 9
shadowData = filter(lambda x: len(x) == lenData,
map(lambda x: x.rstrip().split(":"),
9 years ago
open(fileName)))
shadowData = filter(lambda x: x[0] in migrateusers, shadowData)
shadowData = map(lambda x: (x[0], x[1]), shadowData)
shadowUsers = map(lambda x: x[0], shadowData)
for userName in migrateusers:
if userName in shadowUsers:
9 years ago
userData = filter(lambda x: x[0] == userName,
shadowData)
hashPwd = userData[0][1]
retList.append(hashPwd)
else:
retList.append("")
return retList
9 years ago
def check(self, value):
"""
Check exists password for all migrate users
"""
9 years ago
for user, pwd in zip(self.Get('cl_migrate_user'), value):
if not pwd:
raise PasswordError(
9 years ago
_("Password for user %s missing") % user)
9 years ago
def set(self, value):
"""
Encrypt passwords
"""
reCheck = re.compile("^\$[^$]+\$[^$]+\$.*$")
encryptObj = encrypt()
9 years ago
return map(lambda x: x if reCheck.match(x) or not x else \
encryptObj.getHashPasswd(x, "shadow_ssha256"),
value)
9 years ago
class VariableClAutologin(UserHelper, Variable):
"""
Autologin variable (contains user name for autologin) or
empty string if disable
"""
type = 'choiceedit'
9 years ago
opt = ["--autologin", '-A']
metavalue = "USER"
xorg_need = True
def init(self):
self.label = _("Autologin")
self.help = _("set an autologin for the user, 'off' for disable")
def get(self):
# autologin enable for livecd and all install type CMC
cmdDomainSet = (getValueFromCmdLine(
"calculate", CmdlineParams.DomainPassword) or
getValueFromCmdLine(
"calculate", CmdlineParams.Domain) or "")
9 years ago
if (not cmdDomainSet and
self.Get('os_install_root_type') == "livecd") or \
self.Get('os_install_linux_shortname') == "CMC":
nonRootUsers = filter(lambda x: x != "root",
9 years ago
self.Get('cl_migrate_user'))
if nonRootUsers:
return nonRootUsers[0]
else:
return ""
return ""
def set(self, value):
return {'none': '',
'off': ''}.get(value, value)
def choice(self):
yield ("off", _("No autologin"))
for user in (x for x in self.Get('cl_migrate_user')
if x != "root"):
yield (user,user)
9 years ago
def check(self, value):
"""
Autologin only for migrated non-root users
"""
if value and not value in self.Get('cl_migrate_user'):
9 years ago
raise VariableError(_("User %s does not exist") % value)
if value == "root":
9 years ago
raise VariableError(
_("Autologin is unavailable for user %s") % value)
def humanReadable(self):
return self.Get() or _("Not used")
def uncompatible(self):
"""
Network setting up unavailable for flash installation
"""
try:
if (self.Get('cl_action') == 'merge' and
9 years ago
self.Get('client.cl_remote_host')):
return \
_("The autologin is not available with domain workstations")
except DataVarsError:
pass
return UserHelper.uncompatible(self)
9 years ago
class VariableClInstallAutoupdateSet(Variable):
"""
(on or off) autoupdate config from install program for install
"""
type = "bool"
value = "off"
9 years ago
class VariableOsInstallMakeopts(Variable):
"""
Make.conf makeopts
"""
9 years ago
def get(self):
cpunum = self.Get('hr_cpu_num')
if cpunum == "1":
return "-j1"
else:
9 years ago
return "-j%d" % (int(cpunum) + 1)
class VariableOsGrubConf(ReadonlyVariable):
"""
DEPRICATED content of current grub.conf
"""
9 years ago
class VariableOsInstallGrubDevicemapConf(ReadonlyVariable):
"""
DEPRICATED content of device.map file for grub
"""
os_install_grub_devicemap_conf = {}
9 years ago
class VariableClDistfilesPath(Variable):
"""
DISTFILES path
"""
value = '/var/calculate/remote/distfiles'
9 years ago
class VariableClPkgdirPath(Variable):
"""
PKGDIR path
"""
9 years ago
def get(self):
return "/var/calculate/remote/packages/%s/%s" % (
9 years ago
self.Get('os_install_linux_shortname'),
self.Get('os_install_arch_machine'))
class VariableClInstallDevFrom(Variable):
"""
Root device of previous installed os
"""
9 years ago
def set(self, value):
"""
If device in calculate3.env dev_from not exists set ''
"""
12 years ago
if value:
9 years ago
value = getUdevDeviceInfo(name=value).get('DEVNAME', value)
if value in self.Get('os_disk_dev'):
return value
else:
return ""
def get(self):
9 years ago
if (self.Get('cl_autopartition_set') == 'on' and
SchemeOpt.Update in self.Get('cl_autopartition_scheme')):
return self.Select('cl_autopartition_disk_dev',
where='cl_autopartition_disk_scheme',
eq=SchemeDevices.Root2,
9 years ago
limit=1)
return ""
class VariableOsNvidiaMask(ReadonlyVariable):
"""
Get nvidia card mask versions
"""
9 years ago
def get(self):
image = self.Get('cl_image')
try:
if image:
image = image.convertToDirectory()
chrootPath = image.getDirectory()
else:
chrootPath = self.Get("cl_chroot_path")
nvidiaeclass = path.join(chrootPath,
'usr/portage/eclass/nvidia-driver.eclass')
9 years ago
if not os.access(nvidiaeclass, os.R_OK):
return ""
category = "0300"
vendor = "10de:"
lsPciProg = getProgPath("/usr/sbin/lspci")
9 years ago
nvidiacards = filter(lambda x: " %s: " % category in x,
process(lsPciProg, "-d", vendor, "-n"))
if not nvidiacards:
return ""
cardsid = \
9 years ago
map(lambda x: x.groups()[0],
filter(lambda x: x,
map(lambda x: re.search(
"[0-9a-fA-F]{4}:([0-9a-fA-F]{4})", x),
nvidiacards)))
if not cardsid:
return ""
eclassdata = readFile(nvidiaeclass)
drv_categories = re.findall('^drv_([^=]+)="', eclassdata, re.M)
9 years ago
drvs = map(lambda x: (x[0], x[1].replace('\\\n', '').split()),
re.findall(
'\ndrv_(%s)="(.*?)"' % "|".join(drv_categories),
eclassdata, re.S))
mask_categories = re.findall('^mask_([^=]+)="', eclassdata, re.M)
9 years ago
masks = dict(map(lambda x: (x[0], x[1].replace('\\\n', '')),
re.findall('\nmask_(%s)="(.*?)"' % "|".join(
drv_categories),
eclassdata, re.S)))
drvsForCardsid = filter(lambda x: set(x[1]) & set(cardsid), drvs)
if drvsForCardsid and drvsForCardsid[0][0] in masks:
return masks[drvsForCardsid[0][0]]
finally:
if image:
image.close()
return ""
9 years ago
class VariableOsInstallLvmSet(ReadonlyVariable):
"""
Using lvm
"""
type = "bool"
def get(self):
for typeDisk in self.Get('os_install_disk_type'):
if "lvm" in typeDisk.lower():
return "on"
else:
return "off"
9 years ago
class VariableOsInstallMdadmSet(ReadonlyVariable):
"""
Using mdadm
"""
type = "bool"
def get(self):
for typeDisk in self.Get('os_install_disk_type'):
if "raid" in typeDisk.lower():
return "on"
else:
return "off"
9 years ago
class VariableClChrootGrub(ReadonlyVariable):
"""
Chroot for grub-mkconfig
"""
9 years ago
def get(self):
if self.Get('os_install_scratch') == "on":
if self.Get('cl_action') == 'system':
return self.Get('cl_target').mdirectory
else:
9 years ago
return path.join(self.Get('cl_chroot_path'), "mnt/scratch")
else:
return self.Get('cl_chroot_path')
9 years ago
class VariableOsGrub2Path(Variable):
"""
Get Grub2 Install cmd (grub-install or grub2-install)
"""
9 years ago
def get(self):
# find grub2-install
11 years ago
grubInstall = getProgPath('/usr/sbin/grub2-install')
if grubInstall:
return grubInstall
# find grub-install and check, that this is grub2-install (ver 1.99)
11 years ago
grubInstall = getProgPath('/usr/sbin/grub-install')
9 years ago
if grubInstall and filter(lambda x: "1.99" in x or "2." in x,
process(grubInstall, '--version')):
return grubInstall
return ""
9 years ago
class VariableClSetup(Variable):
"""
Type of setup
"""
type = "choice"
value = ""
def choice(self):
return ["audio", "network", "locale", "video", "boot", "users",
"session", ""]
def humanReadable(self):
mapType = {'network': _("network settings"),
'locale': _("localization and time options"),
'video': _("video settings"),
'boot': _("boot parameters"),
'audio': _("audio parameters"),
'session': _("session settings"),
'users': _("user settings")}
9 years ago
return mapType.get(self.Get(), "")
9 years ago
def check(self, value):
if value == "boot" and self.Get('os_install_root_type') == 'livecd':
raise VariableError(
12 years ago
_("Boot configuration is not available on a LiveCD"))
9 years ago
class VariableClLive(Variable):
"""
Apply live templates
"""
12 years ago
value = "off"
type = "bool"
opt = ['--live']
def init(self):
12 years ago
self.label = _("Configure dynamic options only")
self.help = _("configure dynamic options only")
9 years ago
class VariableOsInstallPxe(Variable):
"""
Installation for PXE loading
"""
type = "boot"
value = "off"
untrusted = True
9 years ago
def check(self, value):
if value == "on":
if self.Get('os_linux_system') != "server":
raise VariableError(
9 years ago
_("PXE install is available for Calculate "
"Directory Server only") + '.')
for pkg in ['net-misc/dhcp', 'net-ftp/tftp-hpa',
'net-fs/nfs-utils']:
if not isPkgInstalled(pkg):
raise VariableError(
9 years ago
_("For PXE install, you need to install package %s")
% pkg)
for env_fn in ('/etc/calculate/calculate.env',
'/var/lib/calculate/calculate.env'):
try:
config = cl_ini_parser.iniParser(env_fn)
val = config.getVar('server', 'sr_dhcp_set')
if val.encode('utf-8') == "on":
return
except Exception:
pass
raise VariableError(
9 years ago
_("PXE install is only available if the DHCP "
"service has been configured first"))
class VariableOsInstallPxePath(Variable):
"""
Path to PXE installation
"""
value = "/var/calculate/pxe"
opt = ['--pxe-path']
def init(self):
12 years ago
self.label = _("Installation path")
self.help = _("path for PXE install")
9 years ago
class VariableOsInstallUefiSet(Variable):
"""
Install in UEFI
"""
9 years ago
type = "bool"
opt = ['--uefi']
def init(self):
self.label = _("UEFI boot")
self.help = _("use UEFI boot")
def get(self):
if self.Get('cl_autopartition_set') == 'on':
return self.Get('cl_autopartition_uefi_set')
else:
if self.Get('os_install_disk_efi') or \
9 years ago
"/boot/efi" in self.Get('os_location_dest'):
if self.Get('os_install_arch_machine') == 'x86_64' and \
9 years ago
self.Get('os_install_root_type') != 'flash':
return self.Get('os_uefi_set')
return 'off'
9 years ago
def check(self, value):
if value == 'on':
if self.Get('os_uefi_set') == 'off' and \
9 years ago
self.Get('os_install_root_type') == 'hdd':
raise VariableError(
9 years ago
_("Your system must be loaded in UEFI for using this "
"bootloader"))
if not 'gpt' in self.Get('os_device_table'):
raise VariableError(
_("GPT is needed for using the UEFI bootloader"))
9 years ago
if not (self.Get('os_install_disk_efi') or
"/boot/efi" in self.Get('os_location_dest')):
raise VariableError(
_("A EF00 partition is needed for using "
"the UEFI bootloader"))
if self.Get('os_install_arch_machine') != 'x86_64':
raise VariableError(
_("Architecture of the target system must be x86_64"))
if self.Get('os_install_root_type') == 'flash':
raise VariableError(
_("This option not used for Flash install"))
def uncompatible(self):
"""
Uncompatible with autopartition
"""
if self.Get('cl_autopartition_set') == "on":
return \
_("The layout is not available with autopartitioning")
if self.Get('os_install_root_type') == 'flash':
return \
_("This option not used for Flash install")
return ""
9 years ago
class VariableOsInstallUefiBriefSet(VariableOsInstallUefiSet):
def uncompatible(self):
if self.Get('os_install_root_type') == 'flash':
return _("This option not used for Flash install")
return ""
9 years ago
def get(self):
return self.Get('os_install_uefi_set')
9 years ago
class VariableOsInstallGrubTerminal(Variable):
"""
Gfxmode
"""
9 years ago
type = "choice"
opt = ['--grub-terminal']
metavalue = "TERMINAL"
def init(self):
self.label = _("Grub terminal")
self.help = _("grub terminal")
def get(self):
cmdLine = '/proc/cmdline'
if 'grub_nogfxmode' in readFile(cmdLine):
return 'console'
grubDefault = path.join(self.Get('cl_chroot_path'),
'etc/default/grub')
9 years ago
if getValueFromConfig(grubDefault, 'GRUB_TERMINAL') == 'console':
return 'console'
grubCfg = '/boot/grub/grub.cfg'
9 years ago
if re.search('^terminal_output\s*console', readFile(grubCfg), re.M):
return 'console'
return 'gfxterm'
def choice(self):
9 years ago
return ['gfxterm', 'console']
def uncompatible(self):
"""
Grub setting up unavailable for flash installation
"""
if self.Get('os_install_root_type') == 'flash':
return _("Grub configuration unavailable for Flash install")
return ""
9 years ago
class PackageCheckVariable(ReadonlyVariable):
"""
Конструктор для переменных проверки установлен ли пакет
11 years ago
"""
image = False
package = None
11 years ago
type = "bool"
image_variable = "cl_image"
prefix_variable = "cl_chroot_path"
11 years ago
def get(self):
try:
if self.image:
image = self.Get(self.image_variable)
if image:
with image as distr:
distrPath = image.getDirectory()
9 years ago
if isPkgInstalled(self.package, prefix=distrPath):
return "on"
else:
prefix = self.Get(self.prefix_variable)
if isPkgInstalled(self.package, prefix=prefix):
return "on"
9 years ago
except Exception:
pass
return "off"
11 years ago
9 years ago
class VariableOsInstallAlsaSet(PackageCheckVariable):
"""
Установлен ли media-sound/alsa-utils
"""
image = True
package = "media-sound/alsa-utils"
9 years ago
class VariableOsInstallX11ServerSet(PackageCheckVariable):
"""
Установлен ли x11-base/xorg-server
"""
image = True
package = "x11-base/xorg-server"
class VariableOsInstallSplashSet(Variable):
"""
Переменная отображать splash при загрузки
"""
type = "bool"
value = "on"
9 years ago
class FlashUncompatible(VariableInterface):
def uncompatible(self):
"""
Update setting up unavailable for flash installation
"""
if self.Get('os_install_root_type') == 'flash':
return \
_("Update configuration unavailable for Flash install")
return ""
9 years ago
try:
import calculate.update.variables.update as update
class VariableClInstallAutocheckSet(FlashUncompatible,
update.VariableClUpdateAutocheckSet):
def get(self):
return self.Get('update.cl_update_autocheck_set')
class VariableClInstallAutocheckInterval(FlashUncompatible,
9 years ago
update.VariableClUpdateAutocheckInterval):
def get(self):
return self.Get('update.cl_update_autocheck_interval')
class VariableClInstallCleanpkgSet(FlashUncompatible,
9 years ago
update.VariableClUpdateCleanpkgSet):
def get(self):
return self.Get('update.cl_update_cleanpkg_set')
class VariableClInstallOtherSet(FlashUncompatible,
9 years ago
update.VariableClUpdateOtherSet):
def get(self):
return self.Get('update.cl_update_other_set')
except ImportError:
9 years ago
update = None
class VariableClInstallAutocheckSet(FlashUncompatible, Variable):
value = "off"
class VariableClInstallAutocheckInterval(FlashUncompatible, Variable):
value = ""
class VariableClInstallCleanpkgSet(FlashUncompatible, Variable):
value = "off"
class VariableClInstallOtherSet(FlashUncompatible, Variable):
value = "off"