#-*- coding: utf-8 -*- # Copyright 2010 Mir 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. from cl_install import cl_install, InstallError, __app__, __version__ from cl_opt import opt from cl_share_cmd import share_cmd import re import sys from cl_lang import lang lang().setLanguage(sys.modules[__name__]) DESCRIPTION = _("The Calculate Linux installation and configuration utility") CMD_OPTIONS = [{'shortOption':"d", 'longOption':"disk", 'optVal':"DISK[:[DIR:FILESYSTEM:OPTIONS]]", 'action':'append', 'help':_("the DISK for installation, which mounted to DIR") }, {'shortOption':"b", 'longOption':"bind", 'optVal':"SRC_DIR:DEST_DIR", 'action':'append', 'help':_("bind mount point for instalation") }, {'longOption':"mbr", 'optVal':"DEVICE", 'help':_("boot disk for the installed system \ (to be recorded MBR)") }, {'shortOption':"w", 'longOption':"swap", 'optVal':"SWAP_DISK", 'action':'append', 'help':_("the SWAP_DISK for installation") }, {'shortOption':"f", 'longOption':"force", 'help':_("no questions during the install process") }, {'shortOption':"s", 'longOption':"os", 'optVal':"SYSTEM", 'type':'choice', 'choices':['cld','cds','cls','css','cldg','cldx'], 'help':_("select operation system") }, {'shortOption':"l", 'longOption':"lang", 'optVal':"LANG", 'help':_("set language") }, {'shortOption':"u", 'longOption':"user", 'optVal':"USER", 'action':'append', 'help':_("add user to installed system") }, {'longOption':"live", 'help':_("configure current system") }, {'longOption':"proxy", 'help':_("set proxy server for system") }, {'longOption':"ntp", 'help':_("set ntp server for system") } ] #{'shortOption':"b", #'longOption':"build", #'help':_("installation for assembling") #}] class install_cmd(cl_install,share_cmd): """Class for work with cl_install by console""" def __init__(self): self.optobj = opt(package=__app__, version=__version__, description=DESCRIPTION, option_list= CMD_OPTIONS + opt.variable_control + opt.color_control, check_values=self.checkOpts) cl_install.__init__(self) # names incompatible options with --live self.optionsLiveIncompatible = ["d", "b", "mbr", "w", "f", "s"] def _getNamesAllSetOptions(self): """Выдает словарь измененных опций""" 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 checkIncompatibeLive(self): incompatible = list(set(self._getNamesAllSetOptions()) & set(self.optionsLiveIncompatible)) if incompatible: self.optobj.error(_("incompatible options")+":"+" %s"\ %self.getStringIncompatibleOptions(incompatible+["live"])) def checkOpts(self, values, args): """Check values all specified options.""" if len(args) > 0: self.optobj.error(_("unrecognized option") + ": %s"% "".join(args)) if values.live: self.checkIncompatibeLive() else: if values.d == None: values.d = self.detectPreviousSystem() if values.v is None and \ values.d is None: 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(_("option %s:") %"d" +\ " " + _("disk specifing error: '%s'")\ %", ".join(wrongValue)) if values.s: choices = ['cld','cds','cls','css','cldg','cldx'] if not values.s.lower() in choices: choices = ", ".join(map(repr, choices)) self.optobj.error(_("option %s:")%"s"+ " " +\ _("invalid choice: %r")%values.s+ " " +\ _("(choose from %s)")%choices) # check syntax SRC_DIR:DEST_DIR if values.b: reTrueBind = re.compile("^[^:]+:[^:]+$") wrongValue = filter(lambda x: not reTrueBind.match(x),values.b) if wrongValue: self.optobj.error(_("option %s:") %"b" +\ " " + _("mount bind specifing error: '%s'")\ %", ".join(wrongValue)) # 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(_("option %s:") %"w" +\ " " + _("mount bind specifing error: '%s'")\ %", ".join(wrongValue)) #check boot device if values.mbr: bootDisk = values.mbr reBootDisk = re.compile("^/dev/.+[^\d]$") 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.setAllLocaleByLang(lang): return True else: self.printERROR(_("specified lang %s is unsupported")%lang) return False def setVars(self,options): """Process setting values for variables""" if options.set: for vals in options.set: for val in vals.split(','): k,o,v = val.partition('=') if self.clVars.exists(k): if not self.clVars.SetWriteVar(k,v): return False else: self.printERROR(_('variable %s not found')%k) return False if options.live: self.clVars.Set('cl_image','',True) self.clVars.Get('cl_image') if options.s: self.setLinuxName(options.s.upper()) return True def checkAndSetInstallOptions(self,diskOptions, swapOptions, bindOptions): """Check and set disk, swap and bind cmd options""" listDiskOptions = [] listBindOptions = [] listSwapOptions = [] if diskOptions: listDiskOptions = self._parseOptDisk(diskOptions) if listDiskOptions is False: return False if bindOptions: listBindOptions = self._parseOptBind(bindOptions) if listBindOptions is False: return False if swapOptions: listSwapOptions = self._parseOptSwap(swapOptions) if listSwapOptions is False: return False if not self.setInstallOptions(listDiskOptions, listBindOptions, listSwapOptions): return False return True def displayVars(self,vars): """Process displaying variables""" self.clVars.printVars() 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""" 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""" listNameOptions = ["dev","mountPoint","fileSystem","options"] 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)) 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.applyTemplatesForSystem(): return True else: return False def installSystem(self, force=False, bootDisk=None, users=[]): if cl_install.installSystem(self, force=force, bootDisk=bootDisk, users=users): return True else: return False