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

570 lines
17 KiB

#-*- coding: utf-8 -*-
# Copyright 2008-2012 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.
import os
import sys
import re
from os import path
from calculate.lib.datavars import Variable,VariableError,ReadonlyVariable, \
TableVariable,PasswordError
from calculate.install.fs_manager import FileSystemManager
from calculate.lib.utils.files import (readFile,getProgPath,process,
readLinesFile)
from calculate.lib.utils.common import getPasswdUsers,getUserGroups,getGroups
from calculate.lib.utils.portage import isPkgInstalled
from calculate.lib.utils.device import getUdevDeviceInfo
from crypt import crypt
from calculate.lib.encrypt import encrypt
import calculate.lib.cl_template as cl_template
from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_install3',sys.modules[__name__])
class UserHelper:
"""
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':
return _("User configuration unavailable for Flash install")
if self.Get('os_install_x11_server_set') == 'no' and self.xorg_need:
return _("Autologin is available for Xorg sessions only")
return ""
class VariableOsInstallScratch(Variable):
"""
Install system in scratch mode
"""
type = "bool"
opt = ['--build']
def init(self):
self.label = _("Builder mode")
self.help = _("build installation")
def get(self):
# for installation default - normal system
if self.Get('cl_action') == 'system':
return "off"
else:
return self.Get('os_scratch')
def check(self,value):
if value == "on":
# scratch not use for falsh and multipartition
if self.Get('os_install_root_type') == "flash":
raise VariableError(
_("Flash install does not support the builder mode"))
if filter(lambda x: not x in ('/','swap'),
self.Get('os_install_disk_mount')):
raise VariableError(
_("The builder mode does not support "
"multipartition install"))
def uncompatible(self):
"""
Unavailable for flash installation
"""
if self.Get('os_install_root_type') == 'flash':
return _("Flash install does not support the builder mode")
class VariableOsFormatType(ReadonlyVariable):
"""
Filesystem format support by calcualte-install
"""
type = "list"
def get(self):
"""Filesystem format support by calcualte-install"""
return FileSystemManager.supportFS.keys()
class VariableOsFormatUse(ReadonlyVariable):
"""
Avialable format by mkfs utility
"""
type = "list"
# (on or off) autoupdate config from install program
cl_autoupdate_set = {'value': "off",
'type': "bool",
'value': "off"}
def get(self):
return map(lambda x:"yes"
if path.exists(FileSystemManager.supportFS[x]["format"])
else "no", self.Get('os_format_type'))
class VariableClMigrateRootPwd(UserHelper,Variable):
"""
Root password
"""
type = "password"
opt = ["--root-password"]
metavalue = 'PASSWORD'
untrusted = True
def init(self):
self.help = _("specify the root password")
self.label = _("Root password")
def get(self):
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 ""
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")
def check(self,value):
if not value:
raise PasswordError(_("Password for user %s missing")%"root")
class VariableClMigrateData(UserHelper,TableVariable):
"""
User migrate data table
"""
type = 'table'
opt = ["--users","-u"]
metavalue = 'USERS'
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")
class VariableClMigrateUser(UserHelper,Variable):
"""
Migrate users list
"""
type = 'list'
def init(self):
self.label = _("Login")
def get(self):
"""
Migrating users (users above 1000 uid)
"""
return filter("root".__ne__,getPasswdUsers())
class VariableClMigrateUserGroups(UserHelper,Variable):
"""
Migrate users groups
"""
type = 'choice-list-list'
defaultGroupList = ["users","wheel","audio","cdrom","video",
"cdrw","usb","plugdev","games","lp","scanner","uucp"]
def getDefaultGroups(self):
return list(set(self.defaultGroupList)&set(getGroups()))
def init(self):
self.label = _("Groups")
def set(self,value):
value = map(lambda x: x \
if x and any(x) else self.getDefaultGroups(),
value)
return value
def get(self):
"""
User groups
"""
passwdList = getPasswdUsers()
return map(lambda x:getUserGroups(x) \
if x in passwdList else self.getDefaultGroups(),
self.Get('cl_migrate_user'))
def choice(self):
"""
Available groups
"""
return getGroups()
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:
lenData=9
shadowData = filter(lambda x: len(x)==lenData,
map(lambda x: x.rstrip().split(":"),
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:
userData = filter(lambda x: x[0]==userName,
shadowData)
hashPwd = userData[0][1]
retList.append(hashPwd)
else:
retList.append("")
return retList
def check(self,value):
"""
Check exists password for all migrate users
"""
for user,pwd in zip(self.Get('cl_migrate_user'),value):
if not pwd:
raise PasswordError(
_("Password for user %s missing")%user)
def set(self,value):
"""
Encrypt passwords
"""
reCheck = re.compile("^\$[^$]+\$[^$]+\$.*$")
encryptObj = encrypt()
return map(lambda x:x if reCheck.match(x) or not x else \
encryptObj.getHashPasswd(x, "shadow_ssha256"),
value)
class VariableClAutologin(UserHelper,Variable):
"""
Autologin variable (contains user name for autologin) or
empty string if disable
"""
type = 'choiceedit'
opt = ["--autologin",'-A']
metavalue = "USER"
xorg_need = True
def init(self):
self.label = _("Autologin")
self.help = _("add an autologin user to the installed system")
def get(self):
# autologin enable for livecd and all install type CMC
if self.Get('os_install_root_type') == "livecd" or \
self.Get('os_install_linux_shortname') == "CMC":
nonRootUsers = filter(lambda x: x != "root",
self.Get('cl_migrate_user'))
if nonRootUsers:
return nonRootUsers[0]
else:
return ""
return ""
def choice(self):
return [""]+filter(lambda x:x != "root",self.Get('cl_migrate_user'))
def check(self,value):
"""
Autologin only for migrated non-root users
"""
if value and not value in self.Get('cl_migrate_user'):
raise VariableError(_("User %s does not exist")%value)
if value == "root":
raise VariableError(_("Autologin is unavailable for user %s")%value)
def humanReadable(self):
return self.Get() or _("Not used")
class VariableClInstallAutoupdateSet(Variable):
"""
(on or off) autoupdate config from install program for install
"""
type = "bool"
value = "off"
class VariableOsInstallMakeopts(Variable):
"""
Make.conf makeopts
"""
def get(self):
cpunum = self.Get('hr_cpu_num')
if cpunum == "1":
return "-j1"
else:
return "-j%d"%(int(cpunum)+1)
class VariableOsGrubConf(ReadonlyVariable):
"""
DEPRICATED content of current grub.conf
"""
class VariableOsInstallGrubDevicemapConf(ReadonlyVariable):
"""
DEPRICATED content of device.map file for grub
"""
os_install_grub_devicemap_conf = {}
class VariableClDistfilesPath(Variable):
"""
DISTFILES path
"""
value = '/var/calculate/remote/distfiles'
class VariableClPkgdirPath(Variable):
"""
PKGDIR path
"""
def get(self):
return "/var/calculate/remote/packages/%s/%s" % (
self.Get('os_install_linux_shortname'),
self.Get('os_install_arch_machine'))
class VariableOsInstallDevFrom(Variable):
"""
Root device of previous installed os
"""
value = ""
def set(self,value):
"""
If device in calculate3.env dev_from not exists set ''
"""
if value:
value = getUdevDeviceInfo(name=value).get('DEVNAME',value)
if value in self.Get('os_disk_dev'):
return value
else:
return ""
class VariableClInstallAutoupdateSet(Variable):
"""
Autoupdate for install or configure system
"""
def get_cl_install_autoupdate_set(self):
"""Get autoupdate default value"""
if self.Get('ac_install_system') == "up":
if self.Get('os_install_linux_system') == 'desktop':
return "on"
else:
return "off"
else:
return self.Get('cl_autoupdate_set')
class VariableOsNvidiaMask(ReadonlyVariable):
"""
Get nvidia card mask versions
"""
def get(self):
image = self.Get('cl_image')
try:
if image:
image = image.convertToDirectory()
chrootPath = image.getDirectory()
chrootPath = image.getDirectory()
else:
chrootPath = self.Get("cl_chroot_path")
nvidiaeclass = path.join(chrootPath,
'usr/portage/eclass/nvidia-driver.eclass')
if not os.access(nvidiaeclass,os.R_OK):
return ""
category = "0300"
vendor = "10de:"
lsPciProg = getProgPath("/usr/sbin/lspci")
nvidiacards = filter(lambda x:" %s: "%category in x,
process(lsPciProg,"-d",vendor,"-n"))
if not nvidiacards:
return ""
cardsid = \
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)
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)
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 ""
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"
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"
class VariableClChrootGrub(ReadonlyVariable):
"""
Chroot for grub-mkconfig
TODO: check for install scratch system.
"""
def get(self):
if self.Get('os_install_scratch') == "on":
return path.join(self.Get('cl_chroot_path'),"mnt/scratch")
else:
return self.Get('cl_chroot_path')
class VariableOsGrub2Path(Variable):
"""
Get Grub2 Install cmd (grub-install or grub2-install)
"""
def get(self):
# find grub2-install
grubInstall = getProgPath('/sbin/grub2-install')
if grubInstall:
return grubInstall
# find grub-install and check, that this is grub2-install (ver 1.99)
grubInstall = self.getProgPath('/sbin/grub-install')
if grubInstall and filter(lambda x:"1.99" in x,
process(grubInstall,'-v')):
return grubInstall
return ""
class VariableClSetup(Variable):
"""
Type of setup
"""
type = "choice"
value = ""
def choice(self):
return ["network","locale","video","boot","users",""]
def humanReadable(self):
mapType = {'network':_("network settings"),
'locale':_("localization and time options"),
'video':_("video settings"),
'boot':_("boot parameters"),
'users':_("user settings") }
return mapType.get(self.Get(),"")
def check(self,value):
if value == "boot" and self.Get('os_install_root_type') == 'livecd':
raise VariableError(
_("Boot configuration is not available on a LiveCD"))
class VariableClLive(Variable):
"""
Apply live templates
"""
value = "off"
type = "bool"
opt = ['--live']
def init(self):
self.label = _("Configure dynamic options only")
self.help = _("configure dynamic options only")
class VariableOsInstallPxe(ReadonlyVariable):
"""
Installation for PXE loading
"""
type = "boot"
value = "off"
def check(self,value):
if value == "on":
if self.Get('os_linux_system') != "server":
raise VariableError(
_("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(
_("For PXE install, you need to install package %s")
%pkg)
try:
config = cl_template.iniParser('/etc/calculate/calculate.env')
val = config.getVar('server','sr_dhcp_set')
if val.encode('utf-8') == "on":
return
except:
pass
raise VariableError(
_("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):
self.label = _("Installation path")
self.help = _("path for PXE install")