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-2.2-install/pym/cl_install_cmd.py

613 lines
25 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.
import re
import sys
from cl_install import cl_install, InstallError, __app__, __version__,\
get_install_errors
from cl_vars_share import varsShare
from cl_opt import opt
from cl_share_cmd import share_cmd
from utils import ip as iputils
from cl_utils import isPkgInstalled
from cl_lang import lang
lang().setLanguage(sys.modules[__name__])
OSSYSTEM_LIST=sorted(varsShare.dictNameSystem.keys())
NM_LIST=sorted(varsShare.dictNetworkManagers.keys())
DESCRIPTION = _("Calculate Linux installation and configuration utility")
CMD_OPTIONS = [{'shortOption':"d",
'longOption':"disk",
'optVal':"DISK[:[DIR:FILESYSTEM:OPTIONS]]",
'action':'append',
'help':_("DISK for installation, will be mounted to DIR") +
". " +
_("DIR set to 'none' will cancel the mount point transfer")
+ ". " +_("For creating bind mount point you have to specify"
" the source directory as DISK")
},
{'shortOption':"w",
'longOption':"swap",
'optVal':"SWAP_DISK",
'action':'append',
'help':_("swap disk for installation")
},
{'longOption':"mbr",
'optVal':"DEVICE",
'help':_("boot disk for the system bound for install "
"(for recording MBR), off - disable MBR writing")
},
{'longOption':"type",
'optVal':"DISKTYPE",
'type':'choice',
'choices':['flash','hdd','usb-hdd'],
'help':_("device type for the system bound for install")
},
{'longOption':'iso',
'optVal':"ISO",
'help':_("ISO image for installation")},
{'shortOption':"s",
'longOption':"os",
'optVal':"SYSTEM",
'type':'choice',
'choices_regignore': OSSYSTEM_LIST,
'help':_("select the operation system")
},
{'longOption':"march",
'optVal':"ARCH",
'type':'choice',
'choices':['i686','x86_64','auto'],
'help':_("select the processor architecture")+ \
_("{0} or {1}").format(" (i686,x86_64","auto)")
},
{'longOption':"build",
'help':_("installation for assemble")
},
{'shortOption':"l",
'longOption':"lang",
'optVal':"LANG",
'help':_("set the language")
},
{'shortOption':"u",
'longOption':"user",
'optVal':"USER",
'action':'append',
'help':_("add a user to the installed system")
},
{'shortOption':"A",
'longOption':"autologin",
'optVal':"USER",
'help':_("add an autologin user to the installed system")
},
{'longOption':"hostname",
'optVal':"HOSTNAME",
'help':_("set the short hostname of the full hostname")
},
{'longOption':"netconf",
'optVal':"NETMANAGER",
'type':'choice',
'choices_regignore': NM_LIST,
'help':_("network manager (%s)")%
_("{0} or {1}").format(",".join(NM_LIST[0:-1]),
NM_LIST[-1])},
{'longOption':"dhcp",
'optVal':"IFACE",
'action':'append',
'help':_("get the ip address by %s for "
"the specified interface")%"DHCP"
},
{'longOption':"ip",
'optVal':"[IFACE:]IP",
'action':'append',
'help':_("ip address with net (example:%s)")%"192.168.1.1/24"
},
{'longOption':"route",
'optVal':"NETWORK:[GATEWAY][:DEV[:SOURCE]]",
'action':'append',
'help':_("add a routing rule")
},
{'longOption':"dns",
'optVal':"DNS",
'help':_("domain name servers (comma-separated)")
},
{'longOption':"proxy",
'optVal':"PROXY",
'help':_("set the proxy server for the system")
},
{'longOption':"ntp",
'optVal':"NTP",
'help':_("set the ntp server for the system")
},
{'longOption':"video",
'optVal':"VIDEODRV",
'help':_("set the video driver")
},
{'shortOption':"X",
'optVal':"<width>x<height>",
'help':_("set Xorg resolution")
},
{'longOption':"fb",
'optVal':"<width>x<height>",
'help':_("set frame buffer resolution")
},
{'longOption':"scheduler",
'optVal':"SCHEDULER",
'help':_("set I/O scheduler")
},
{'longOption':"timezone",
'optVal':"TIMEZONE",
'help':_("set the timezone")
},
{'longOption':"nouuid",
'help':_("do not use UUID")
},
{'longOption':'set'},
{'shortOption':"U",
'longOption':"update",
'help':_("install newer images only")},
{'shortOption':"f",
'longOption':"force",
'help':_("no questions during installation")
},
{'longOption':"startup",
'help':_("configuring the current system")
},
{'longOption':"live",
'help':_("configure only mutable parameters, "
"used in conjunction with the option '--startup'")
},
{'longOption':"install",
'help':_("install the package")
},
{'longOption':"uninstall",
'help':_("uninstall the package")
},
{'longOption':"nospinner",
'help':_("disable the spinner")
},
{'shortOption':"P",
'help':_("use passwords for the users accounts "
"(from standard input)")
},
{'shortOption':'p',
'longOption':"show-partitions",
'help':_("display all partitions")}
]
class OptException(Exception):
pass
class install_cmd(share_cmd):
"""Class for work with cl_install by console"""
def __init__(self):
setpos = \
filter(lambda x:x[1].get('longOption')=="set",
enumerate(CMD_OPTIONS))[0][0]
CMD_OPTIONS[setpos] = opt.variable_set[0]
self.optobj = opt(package=__app__,
version=__version__,
description=DESCRIPTION,
option_list= CMD_OPTIONS + opt.variable_view +
opt.color_control,
check_values=self.checkOpts)
self.logicObj = cl_install()
# names incompatible options with --startup
self.optionsStartupIncompatible = ["type","d", "b", "mbr",
"w", "f","U", "s","install","uninstall","build","u"]
self.optionsDhcpIncompatible = ["ip","gateway","dns"]
self.errorWithExample = \
_("option {optname}: {errormess}:"
" '{value}' (example: '{example}')")
def _getNamesAllSetOptions(self):
"""Get list set options"""
setOptDict = self.optobj.values.__dict__.items()
defaultOptDict = self.optobj.get_default_values().__dict__.items()
return reduce(lambda x,y: x+[y[0][0]],
filter(lambda x:x[0][1] != x[1][1],
zip(setOptDict,defaultOptDict)), [])
def getStringIncompatibleOptions(self,listOpt):
"""Форматированная строка несовместимых опций разделенных ','"""
return ", ".join(map(lambda x: len(x) == 1 and "'-%s'"%x or "'--%s'"%x,
listOpt))
def checkIncompatibleStartup(self):
"""Check incompatible options for option --startup"""
incompatible = list(set(self._getNamesAllSetOptions()) &
set(self.optionsStartupIncompatible))
if incompatible:
self.optobj.error(_("incompatible options")+":"+" %s"\
%self.getStringIncompatibleOptions(incompatible+["startup"]))
def checkIncompatibleDhcp(self):
"""Check incompatible options for option --dchp"""
incompatible = list(set(self._getNamesAllSetOptions()) &
set(self.optionsDhcpIncompatible))
if incompatible:
self.optobj.error(_("incompatible options")+":"+" %s"\
%self.getStringIncompatibleOptions(incompatible+["dhcp"]))
def checkIncompatibleInstallUninstall(self):
"""Check incompatible options for options --install and --uninstall"""
opts = self._getNamesAllSetOptions()
if len(opts)>1:
self.optobj.error(_("incompatible options")+":"+" %s"\
%self.getStringIncompatibleOptions(opts))
def __checkByReg(self,reg="",value="",valueopt="",valuename="",example=""):
"""Check option specifed by value"""
if value:
if not re.match(reg,value):
self.optobj.error(self.errorWithExample.format(
optname=valueopt,
errormess=_("%s specifing error")%valuename,
value=value,
example=example))
def checkOpts(self, values, args):
"""Check values all specified options."""
if len(args) > 0:
self.optobj.error(_("unrecognized option") + ": %s"% "".join(args))
if not values.startup:
if values.live:
errMsg = _("incorrect option") + ":" + " %s" %"--live" +\
": " + _("used with option '--startup'")
self.optobj.error(errMsg)
if values.install or values.uninstall:
self.checkIncompatibleInstallUninstall()
if values.startup:
self.checkIncompatibleStartup()
if values.dhcp:
self.checkIncompatibleDhcp()
if values.A == "root":
self.optobj.error(_("The autologin user cannot be root"))
if not values.v:
if values.filter:
errMsg = _("incorrect option") + ":" + " %s" %"--filter" +\
": " + _("use with option '-v'")
self.optobj.error(errMsg)
if values.xml:
errMsg = _("incorrect option") + ":" + " %s" %"--xml" +\
": " + _("use with option '-v'")
self.optobj.error(errMsg)
self.__checkByReg(reg="^\d+x\d+$",value=values.X,valueopt="-X",
valuename=_("X resolution"),example="1024x768")
self.__checkByReg(reg="^\d+x\d+$",value=values.fb,valueopt="--fb",
valuename=_("frame buffer resolution"),
example="1024x768")
if values.ip:
for ipaddr in values.ip:
if not re.match("^(\w+:)?%s$"%iputils.IP_ADDR_NET,ipaddr):
self.optobj.error(self.errorWithExample.format(
optname="--ip",
errormess=_("%s specifing error")%"ip",
value=ipaddr,
example="eth0:192.168.0.21/16"))
if not values.dns is None:
if not re.match("(^{0}(,{0})*|)$".format(iputils.IP_ADDR),
values.dns):
self.optobj.error(self.errorWithExample.format(
optname="--dns",
errormess=_("%s specifing error")%"dns",
value=values.dns,
example="8.8.8.8"))
if values.route:
for route in values.route:
if not re.match("^({net}|default):(({ipaddr})?"
"(:\w+(:{ipaddr})?)?)?$".format(
net=iputils.IP_ADDR_NET,ipaddr=iputils.IP_ADDR),route):
self.optobj.error(self.errorWithExample.format(
optname="--route",
errormess=_("%s specifing error")%_("route"),
value=route,
example="default:192.168.1.1"))
# if system installation
if values.scheduler:
if not values.scheduler in \
self.logicObj.clVars.Get('os_kernel_schedulers'):
self.optobj.error(self.errorWithExample.format(
optname="--scheduler",
errormess=_("%s specifing error")%"scheduler",
value=values.scheduler,
example="deadline"))
else:
self.logicObj.clVars.Set('os_install_kernel_scheduler',
values.scheduler,force=True)
if not (values.install or values.uninstall
or values.startup or values.live):
if values.v is False and \
not values.p and \
values.d is None and \
not self.logicObj.clVars.Get('os_install_dev_from'):
self.optobj.error(_("need specify disk by '-d' option"))
# check syntax DISK:DIR:FS:'Do I need to format the disk'
if values.d:
reTrueDisk = re.compile("^[^:]+(:[^:]*){0,3}$")
wrongValue = filter(lambda x: not reTrueDisk.match(x),values.d)
if wrongValue:
self.optobj.error(self.errorWithExample.format(
optname="-d",
errormess=_("%s specifing error")%_("disk"),
value=", ".join(wrongValue),
example="/dev/sda2:/:ext4"))
# check syntax SWAP_DISK
if values.w:
reTrueBind = re.compile("^[^:]+$")
wrongValue = filter(lambda x: not reTrueBind.match(x),values.w)
if wrongValue:
self.optobj.error(self.errorWithExample.format(
optname="-w",
errormess=_("%s specifing error")%_("disk"),
value=", ".join(wrongValue),
example="/dev/sda1"))
#check boot device
if values.mbr:
bootDisk = values.mbr
reBootDisk = re.compile("^/dev/.+[^\d]|off$")
if not reBootDisk.match(bootDisk):
self.optobj.error(_("option %s:") %"mbr" + " " +\
_("disk specifing error: '%s'")%bootDisk)
# check syntax --set
self.optobj.checkVarSyntax(values)
return (values, args)
def setLang(self,lang):
"""Process set locales by lang"""
if self.logicObj.setAllLocaleByLang(lang):
return True
else:
self.printERROR(_("specified language %s is unsupported")%lang)
return False
def setProxyNtpHostname(self,proxy,ntp,hostname):
"""Process set locales by lang"""
getVar = self.logicObj.clVars.Get
setVar = self.logicObj.clVars.Set
setWriteVar = self.logicObj.clVars.SetWriteVar
if proxy:
if not setWriteVar('os_install_proxy',proxy):
self.printERROR(get_install_errors(),printBR=False)
return False
if ntp:
if not setWriteVar('os_install_ntp',ntp):
self.printERROR(get_install_errors(),printBR=False)
return False
if hostname:
if "." in hostname:
hostname, op, domain = hostname.partition('.')
setVar('os_install_net_hostname', hostname,True)
setVar('os_install_net_domain', domain,True)
dns_search = getVar("os_install_net_dns_search")
if not domain in dns_search:
setVar("os_install_net_dns_search",domain,True)
else:
setVar('os_install_net_hostname', hostname,True)
return True
def setNetworkParams(self,ipaddrs,routes,dns,setup,dhcps):
"""Set nework params"""
if not dns is None:
self.logicObj.clVars.Set("os_install_net_dns",
dns.replace(',',' '), True)
ipaddrs = map(lambda x:x.split(":"),ipaddrs or [])
routes = map(lambda x:x+[""]*(4-len(x)),
map(lambda x:x.split(":"),routes or []))
dhcps = dhcps or []
if not self.logicObj.setNetwork(ipaddrs,dhcps,routes):
return False
if setup:
if not isPkgInstalled(setup):
self.printERROR(_("Network manager %s is not installed")%setup)
return False
self.logicObj.clVars.Set("os_install_net_conf",setup,True)
return True
def setVars(self,options):
"""Process setting values for variables"""
values = self.optobj.values
if values.video:
if not self.logicObj.setVideo(values.video,
startup=values.startup):
return False
if values.X:
if not self.clVars.Set('os_install_x11_resolution', values.X,
force=True):
return False
if values.fb:
if not self.clVars.Set('os_install_fb_resolution',
"%s-32"%values.fb,
force=True):
return False
if values.timezone:
if not self.logicObj.setTimezone(values.timezone):
return False
if options.set:
for vals in options.set:
for val in vals.split(','):
k,o,v = val.partition('=')
if self.logicObj.clVars.exists(k):
if self.logicObj.clVars.SetWriteVar(k,v) == False:
self.printERROR(get_install_errors(),printBR=False)
return False
else:
self.printERROR(_('variable %s not found')%k)
return False
return True
def setAction(self,startup,live):
"""Set action by configuration or install system"""
if live:
self.logicObj.clVars.Set('cl_action',"live",True)
elif startup:
self.logicObj.clVars.Set('cl_action',"merge",True)
else:
self.logicObj.clVars.Set('cl_action',"system",True)
def checkAndSetInstallOptions(self,diskOptions, swapOptions,
usersOptions, autologinOptions):
"""Check and set disk, swap and bind cmd options"""
if self.optobj.values.s:
self.logicObj.setLinuxName(self.optobj.values.s.upper())
if self.optobj.values.march:
self.logicObj.setArchitecture(self.optobj.values.march)
if self.optobj.values.nouuid:
self.logicObj.clVars.Set('cl_uuid_set','off',True)
if self.optobj.values.build:
self.logicObj.clVars.Set('os_install_scratch',"on",True)
else:
self.logicObj.clVars.Set('os_install_scratch',"off",True)
if self.optobj.values.type:
self.logicObj.clVars.Set('os_install_root_type',
self.optobj.values.type, True)
if self.optobj.values.iso:
if not self.logicObj.setIso(self.optobj.values.iso):
return False
listDiskOptions = []
listBindOptions = []
listSwapOptions = []
if diskOptions:
listDiskOptions = self._parseOptDisk(diskOptions)
if listDiskOptions is False:
return False
listBindOptions = self._parseOptBind(diskOptions)
if listBindOptions is False:
return False
if swapOptions:
listSwapOptions = self._parseOptSwap(swapOptions)
if listSwapOptions is False:
return False
if not self.logicObj.setInstallOptions(listDiskOptions, listBindOptions,
listSwapOptions, usersOptions,
autologinOptions,
self.optobj.values.mbr):
return False
return True
def _parseOptSwap(self, listOpt):
"""Parse value cmd option --swap"""
listNameOptions = ["dev"]
lenOptions = len(listNameOptions)
itemOptions = map(lambda x: (x,''), listNameOptions)
rawListOpt = map(lambda x: filter(lambda y: y, x.split(':')), listOpt)
sameLenListOpt = []
for listData in rawListOpt:
lenListData = len(listData)
if lenListData>1:
errOpt = ":".join(filter(lambda x: x, listData))
self.printERROR(_("incorrect '%s'")%errOpt)
return False
dictOpt = {}
dictOpt.update(zip(map(lambda x:x[0],itemOptions),listData))
sameLenListOpt.append(dictOpt)
return sameLenListOpt
def _parseOptBind(self, listOpt):
"""Parse value cmd option --bind"""
listOpt = filter(lambda x:not x.startswith('/dev/'),listOpt)
listNameOptions = ["srcMountPoint", "destMountPoint"]
lenOptions = len(listNameOptions)
itemOptions = map(lambda x: (x,''), listNameOptions)
rawListOpt = map(lambda x: filter(lambda y: y, x.split(':')), listOpt)
sameLenListOpt = []
for listData in rawListOpt:
lenListData = len(listData)
if lenListData < lenOptions:
listData += ['']*(lenOptions-lenListData)
dictOpt = {}
dictOpt.update(zip(map(lambda x: x[0], itemOptions),listData))
srcDir = dictOpt["srcMountPoint"]
destDir = dictOpt["destMountPoint"]
if not (srcDir and destDir):
errOpt = ":".join(filter(lambda x: x, listData))
self.printERROR(_("incorrect '%s'")%errOpt)
return False
sameLenListOpt.append(dictOpt)
return sameLenListOpt
def _parseOptDisk(self, listOpt):
"""Parse value cmd option --disk"""
listOpt = filter(lambda x:x.startswith('/dev/'),listOpt)
listNameOptions = ["dev","mountPoint","fileSystem","options"]
lenOptions = len(listNameOptions)
itemOptions = map(lambda x: (x,''), listNameOptions)
rawListOpt = map(lambda x: x.split(':'), listOpt)
sameLenListOpt = []
for listData in rawListOpt:
lenListData = len(listData)
if lenListData < lenOptions:
listData += ['']*(lenOptions-lenListData)
dictOpt = {}
dictOpt.update(zip(map(lambda x: x[0],itemOptions), listData))
options = []
strOptions = dictOpt["options"]
if strOptions:
options = filter(lambda x: x, strOptions.split(','))
dictOpt["options"] = options
sameLenListOpt.append(dictOpt)
return sameLenListOpt
def templateSelect(self,template):
"""Process template appling"""
if self.logicObj.applyTemplatesForSystem():
return True
else:
return False
def installSystem(self, force=False, bootDisk=None, users=[],
stdinReadPwd=False, builder=False, flagSpinner=True,
update=False):
"""Run install system"""
if self.logicObj.installSystem(force=force, bootDisk=bootDisk,
stdinReadPwd=stdinReadPwd, builder=builder,
flagSpinner=flagSpinner,update=update):
if self.logicObj.clVars.Get('os_install_root_type') != "flash":
self.defaultPrint("\n")
self.defaultPrint(_("To apply the changes you have to reboot")+
".\n")
return True
else:
return False
def showPartitions(self):
self.logicObj.printAllPartitonsTable()
def configureSystem(self,autologin):
"""Run configure system"""
if self.logicObj.configureSystem(autologin):
return True
else:
return False
def installPackage(self):
"""Run package installation"""
if self.logicObj.installPackage():
return True
else:
return False
def uninstallPackage(self):
"""Run package uninstallation"""
if self.logicObj.uninstallPackage():
return True
else:
return False