From 7f747d96e11356fe2bab6a2ef950f0da6c02a043 Mon Sep 17 00:00:00 2001 From: Mike Hiretsky Date: Tue, 28 Sep 2010 18:19:08 +0400 Subject: [PATCH] Added iso creating and rescratch function --- pym/cl_builder.py | 276 ++++++++++++++++++++++++++++++++++++++++- pym/cl_fill_builder.py | 84 ++++++++----- pym/cl_image_cmd.py | 18 ++- pym/cl_share_cmd.py | 3 + pym/cl_vars_builder.py | 19 ++- 5 files changed, 360 insertions(+), 40 deletions(-) diff --git a/pym/cl_builder.py b/pym/cl_builder.py index b1d79ee..f48ec91 100644 --- a/pym/cl_builder.py +++ b/pym/cl_builder.py @@ -22,20 +22,50 @@ import re import sys import traceback from os import path -from cl_utils import process +from cl_utils import process,pathJoin from subprocess import STDOUT,PIPE from cl_print import color_print from cl_datavars import DataVars from shutil import copy2 as copy_with_perm +from cl_distr import IsoDistributive, DirectoryDistributive, \ + DistributiveError +from cl_template import template +from cl_vars_share import varsShare from cl_kernel_utils import KernelConfig,InitRamFs from cl_lang import lang +from server.utils import dialogYesNo +import cl_overriding class printNoColor: def colorPrint(self,attr,fg,bg,string): sys.stdout.write(string) +class BuilderError(Exception): + """Installation Error""" + builder_errors = "" + + def installExit(self,*args,**kwars): + raise BuilderError(self.__class__.builder_errors) + + def overprintERROR(self,error): + self.__class__.builder_errors += str(error) + "\n" + + def getBuilderErrors(self): + return self.__class__.builder_errors + + def popBuilderErrors(self): + res = self.__class__.builder_errors + self.__class__.builder_errors = "" + return res + + def getOverrideMethods(self): + return self.installExit, self.overprintERROR + +cl_overriding.exit, cl_overriding.printERROR = \ + BuilderError().getOverrideMethods() + class DataVarsBuilder(DataVars): """Variable class for installation""" @@ -61,3 +91,247 @@ class cl_builder(color_print): self.clVars = DataVarsBuilder() self.clVars.importBuilder() self.clVars.flIniFile() + self.startMessage = "" + self.clTempl = None + self.force = False + + def applyTemplatesForSquash(self,directory): + """Apply templates for root of system.""" + #self.clVars.Set("cl_root_path","/", True) + self.clVars.Set("cl_action","squash", True) + self.clVars.Set("cl_chroot_path",directory, True) + self.clTempl = template(self.clVars) + dirsFiles = self.clTempl.applyTemplates() + self.clTempl.closeFiles() + if self.clTempl.getError(): + self.printERROR(self.clTempl.getError()) + return False + else: + return dirsFiles + + def applyTemplatesForIso(self,directory): + """Apply templates for root of system.""" + #self.clVars.Set("cl_root_path","/", True) + self.clVars.Set("cl_action","iso", True) + chrootPath=pathJoin(directory, + self.clVars.Get('cl_builder_squash_path')) + self.clVars.Set("cl_chroot_path",chrootPath, True) + self.clVars.Set("cl_root_path","..", True) + self.clTempl = template(self.clVars) + dirsFiles = self.clTempl.applyTemplates() + self.clTempl.closeFiles() + if self.clTempl.getError(): + self.printERROR(self.clTempl.getError()) + return False + else: + return dirsFiles + + def printMessageForTest(self,message): + """Print waiting message and OK or Error by func result""" + message = "%s ..." % message + self.printSUCCESS(message,printBR=False) + self.startMessage = message + + def printByResult(self,result,failMessage=None): + """Print message and result""" + if self.startMessage: + self.defaultPrint("\r") + self.printLine((('greenBr',' * '), + ('',self.startMessage), + ), + (('',''), + ), 0, False) + self.printRight(self.lenString(self.startMessage)+5,4) + if result: + self.printLine((('blueBr','['), + ('greenBr',' ok '), + ('blueBr',']')),[]) + else: + self.printLine((('blueBr','['), + ('redBr',' !! '), + ('blueBr',']')),[]) + if failMessage: + self.printERROR(failMessage) + self.startMessage = "" + + def prepareSourceDistributive(self,distr): + self.applyTemplatesForSquash(distr.convertToDirectory().getDirectory()) + + def isoPrepacking(self,directory): + self.printByResult(True) + self.applyTemplatesForIso(directory) + self.printMessageForTest(_("Releasing source data")) + self.sourceDistr.close() + self.printByResult(True) + self.sourceDistr = None + self.printMessageForTest(_("Creating iso image")) + + def flashPrepacking(self,directory): + self.printByResult(True) + self.applyTemplatesForIso(directory) + self.printMessageForTest(_("Releasing source data")) + self.sourceDistr.close() + self.sourceDistr = None + + def printInfo(self): + self.printSUCCESS(_("Creating image of") + " Calculate Linux") + self.defaultPrint("%s\n"%_("System information")) + subname = self.clVars.Get('os_builder_linux_subname') + subname = (" %s"%subname) if subname else "" + self.printSUCCESS(_("Building system")+": %s"% + self.clVars.Get('os_builder_linux_name')+subname) + self.printSUCCESS(_("System version")+": %s"% + self.clVars.Get('os_builder_linux_ver')) + self.printSUCCESS(_("Machine hardware name")+": %s"% + self.clVars.Get('os_builder_arch_machine')) + self.defaultPrint("%s\n"%_("Perform pre-install checkups")) + + if self.clVars.Get('cl_builder_image'): + self.printSUCCESS(_("Image will be created at: %s\n")% + self.clVars.Get('cl_builder_image')) + else: + self.printWARNING("No path for image creating.") + + def printRescratchInfo(self): + self.printSUCCESS(_("Rebuilding live image of") + " Calculate Linux") + self.defaultPrint("%s\n"%_("System information")) + subname = self.clVars.Get('os_builder_linux_subname') + subname = (" %s"%subname) if subname else "" + self.printSUCCESS(_("Building system")+": %s"% + self.clVars.Get('os_builder_linux_name')+subname) + self.printSUCCESS(_("System version")+": %s"% + self.clVars.Get('os_builder_linux_ver')) + self.printSUCCESS(_("Machine hardware name")+": %s"% + self.clVars.Get('os_builder_arch_machine')) + self.defaultPrint("%s\n"%_("Perform pre-install checkups")) + + self.printSUCCESS(_("Image will be created in: %s\n")% + self.clVars.Get('cl_builder_iso_path')) + + def checkVariables(self,rescratch=False): + """Check values of variables""" + buildDirectory = self.clVars.Get('cl_builder_iso_path') + if path.realpath(self.clVars.Get('cl_builder_path')) == "/": + self.printERROR("Source system should not be '/'") + return False + if self.clVars.Get('os_builder_linux_ver') == "0": + self.printERROR("Can not found distributive version") + return False + elif not self.clVars.Get('os_builder_linux_shortname') in \ + varsShare.dictNameSystem.keys(): + self.printWARNING("Distributive is not Calculate Linux") + return False + elif not rescratch and path.exists(buildDirectory): + self.printWARNING( + _("Directory '%s' for building iso is already exists")% + buildDirectory) + return False + return True + + def _isoLogic(self,force): + isoFile = self.clVars.Get('cl_builder_image') + buildDirectory = self.clVars.Get('cl_builder_iso_path') + sourceDirectory = self.clVars.Get('cl_builder_path') + bindDirectory = pathJoin(buildDirectory, + self.clVars.Get('cl_builder_squash_path')) + if not self.checkVariables(): + return False + self.printInfo() + self.targetDistr = IsoDistributive(isoFile,bdirectory=buildDirectory) + self.sourceDistr = DirectoryDistributive(sourceDirectory, + mdirectory=bindDirectory) + if not force: + dialogMessage = _("Continue the creating image of the system") \ + + " (yes/no)" + dialogRes = dialogYesNo(dialogMessage) + if dialogRes in (None,False): + return True + self.printMessageForTest(_("Prepare data for live image")) + self.prepareSourceDistributive(self.sourceDistr) + self.printByResult(True) + self.targetDistr.prepareIso = self.isoPrepacking + self.printMessageForTest(_("Creating squash image")) + self.targetDistr.installFrom(self.sourceDistr) + self.printByResult(True) + return True + + def _rescratchLogic(self,force=False): + self.clVars.Set('cl_builder_iso_path','/mnt/flash',True) + buildDirectory = self.clVars.Get('cl_builder_iso_path') + sourceDirectory = self.clVars.Get('cl_builder_path') + bindDirectory = pathJoin(buildDirectory, + self.clVars.Get('cl_builder_squash_path')) + if not self.checkVariables(rescratch=True): + return False + self.printRescratchInfo() + self.targetDistr = IsoDistributive(buildDirectory, + bdirectory=buildDirectory) + self.sourceDistr = DirectoryDistributive(sourceDirectory, + mdirectory=bindDirectory) + if not force: + dialogMessage = _("Continue the rebuilding flash live system") \ + + " (yes/no)" + dialogRes = dialogYesNo(dialogMessage) + if dialogRes in (None,False): + return True + self.printMessageForTest(_("Prepare data for live image")) + self.prepareSourceDistributive(self.sourceDistr) + self.printByResult(True) + self.targetDistr.prepareIso = self.flashPrepacking + self.printMessageForTest(_("Creating squash image")) + self.targetDistr.installFrom(self.sourceDistr) + self.printByResult(True) + return True + + def makeIsoImage(self,force=False): + return self.makeImage(self._isoLogic,force) + + def makeRescratch(self,force=False): + return self.makeImage(self._rescratchLogic,force) + + def makeImage(self,logicFunc,*argv): + """Make iso image by variables""" + self.sourceDistr = None + self.targetDistr = None + error = None + try: + if not logicFunc(*argv): + return False + except (EOFError), e: + error = e + except (BuilderError,DistributiveError),e: + error = e + except (Exception),e: + error = "" + for i in apply(traceback.format_exception, sys.exc_info()): + error += i + except KeyboardInterrupt,e: + self.printByResult(False) + self.printWARNING("Interrupting the iso building") + error = _("Iso building manually interrupt") + if error: + self.printByResult(False) + try: + if self.clTempl: + self.clTempl.closeFiles() + if self.sourceDistr: + self.printMessageForTest(_("Releasing source data")) + self.sourceDistr.close() + self.printByResult(True) + if self.targetDistr: + self.printMessageForTest(_("Unmount built system volume")) + self.targetDistr.close() + self.printByResult(True) + except (BuilderError,DistributiveError),e: + error = "%s\n%s" % (str(error),_("Unmounting error")) + except KeyboardInterrupt,e: + pass + if error: + self.printByResult(False) + if error: + for line in filter(lambda x: x,str(error).split('\n')): + self.printERROR(line) + self.printERROR(_("Iso building failed")) + return False + self.printSUCCESS(_("Iso has built successfully")) + return True diff --git a/pym/cl_fill_builder.py b/pym/cl_fill_builder.py index 6163b0e..e88700f 100644 --- a/pym/cl_fill_builder.py +++ b/pym/cl_fill_builder.py @@ -22,8 +22,9 @@ from cl_kernel import cl_kernel from os import access, R_OK,W_OK from os import path from cl_distr import Distributive -from cl_utils import getTupleVersion +from cl_utils import getTupleVersion,genpassword,pathJoin from operator import itemgetter +from types import ListType class fillVars(object, varsShare): @@ -160,18 +161,10 @@ class fillVars(object, varsShare): return "up" return "" - def get_cl_builder_squash_path(self): - """Directory of system for livecd.squashfs""" - return "/mnt/builder" - - def get_cl_builder_iso_path(self): - """Directory for iso building""" - return "/var/calculate/tmp/iso" - def get_cl_builder_kernel(self): """Kernel image""" - bootdir = path.join(self.Get('cl_builder_squash_path'),'boot') - modulesdir = path.join(self.Get('cl_builder_squash_path'),'lib/modules') + bootdir = path.join(self.Get('cl_builder_path'),'boot') + modulesdir = path.join(self.Get('cl_builder_path'),'lib/modules') validKernel = os.listdir(modulesdir) kernelFiles = self.getFilesByType(bootdir,"Linux kernel") kernelsWithVer = \ @@ -187,7 +180,7 @@ class fillVars(object, varsShare): def get_cl_builder_initrd_install(self): return self.getInitrd(self.Get('os_builder_arch_machine'), self.Get('os_builder_linux_shortname'), - self.Get('cl_builder_squash_path'), + self.Get('cl_builder_path'), self.Get('cl_builder_kernel'), suffix="install") or "" @@ -203,7 +196,7 @@ class fillVars(object, varsShare): def get_os_builder_linux_shortname(self): """Build system shortname""" - systemRoot = self.Get('cl_builder_squash_path') + systemRoot = self.Get('cl_builder_path') return self.getShortnameByMakeprofile(systemRoot) or \ self.getShortnameByIni(systemRoot) or \ self.detectOtherShortname(systemRoot) or \ @@ -212,15 +205,14 @@ class fillVars(object, varsShare): def get_os_builder_linux_ver(self): """Build system ver""" linuxShortName = self.Get("os_builder_linux_shortname") - rootSystem = self.Get('cl_builder_squash_path') + rootSystem = self.Get('cl_builder_path') return self.getVersionFromMetapackage(rootSystem,linuxShortName) or \ self.getVersionFromCalculateIni(rootSystem) or \ - self.getVersionFromGentooFiles(rootSystem) or \ - self.getVersionFromUname() or "0" + self.getVersionFromGentooFiles(rootSystem) or "0" def get_os_builder_arch_machine(self): """Build system arch""" - rootSystem = self.Get('cl_builder_squash_path') + rootSystem = self.Get('cl_builder_path') lib64path = path.join(rootSystem,"lib64") return 'x86_64' if path.lexists(lib64path) else "i686" @@ -231,23 +223,47 @@ class fillVars(object, varsShare): def get_cl_builder_cdname(self): """Cd size specified by name (DVD/CD)""" - squashfile = path.join(self.Get('cl_builder_iso_path'), + squashfile = pathJoin(self.Get('cl_builder_iso_path'), self.Get('cl_builder_current_squash')) - if os.access(squashfile,R_OK): - isosize = path.getsize(squashfile)*1.05 + kernelfile = pathJoin(self.Get('cl_builder_iso_path'), + self.Get('cl_builder_squash_path'), + 'boot', + self.Get('cl_builder_kernel')) + initrdfile = pathJoin(self.Get('cl_builder_iso_path'), + self.Get('cl_builder_squash_path'), + 'boot', + self.Get('cl_builder_initrd_install')) + if os.access(squashfile,R_OK) and os.access(kernelfile,R_OK) and \ + os.access(initrdfile,R_OK): + isosize = path.getsize(squashfile)+path.getsize(kernelfile)+ \ + path.getsize(initrdfile)+2*1024*1024 if isosize > 700*1024*1024: return "DVD" else: return "CD" return "" + def getSquashNum(self,reMatch): + if reMatch.groups()[1] and reMatch.groups()[1].isdigit(): + return int(reMatch.groups()[1]) + else: + return 0 + + def get_cl_builder_remove_squash(self): + """Livecd.squashfs name for del(may be livecd.squashfs.2 and etc)""" + directory = self.Get('cl_builder_iso_path') + if not os.access(directory,R_OK): + return "" + squashfiles = filter(lambda x:x, + map(Distributive.reLive.search, + os.listdir(directory))) + if squashfiles: + return map(lambda x:x.group(), + sorted(squashfiles, key=self.getSquashNum))[:-1] + return "" + def get_cl_builder_current_squash(self): """Livecd.squashfs name (may be livecd.squashfs.2 and etc)""" - def getSquashNum(reMatch): - if reMatch.groups()[1] and reMatch.groups()[1].isdigit(): - return int(reMatch.groups()[1]) - else: - return 0 directory = self.Get('cl_builder_iso_path') if not os.access(directory,R_OK): return "" @@ -255,14 +271,22 @@ class fillVars(object, varsShare): map(Distributive.reLive.search, os.listdir(directory))) if squashfiles: - return "livecd.squashfs.%d"% \ - (getSquashNum(max(squashfiles, key=getSquashNum).group())+1) - return "livecd.squashfs" + return max(squashfiles, key=self.getSquashNum).group() + return "" + + def get_cl_builder_iso_path(self): + directory = "/var/calculate/tmp/iso" + newDirectoryName = directory + while path.exists(newDirectoryName): + newDirectoryName = "%s.%s"%(directory,genpassword(8)) + return newDirectoryName def get_cl_builder_image(self): """Iso image full path""" - paths = filter(lambda x:os.access(x,W_OK), - self.Get('cl_builder_image_path')) + imagepath = self.Get('cl_builder_image_path') + if type(imagepath) != ListType: + imagepath = [imagepath] + paths = filter(lambda x:os.access(x,W_OK), imagepath) if paths: return path.join(paths[0],"%(shortname)s-%(ver)s-%(march)s.iso"% {'shortname':self.Get('os_builder_linux_shortname').lower(), diff --git a/pym/cl_image_cmd.py b/pym/cl_image_cmd.py index b67817f..7ece301 100644 --- a/pym/cl_image_cmd.py +++ b/pym/cl_image_cmd.py @@ -27,7 +27,10 @@ from cl_lang import lang lang().setLanguage(sys.modules[__name__]) DESCRIPTION = _("The Calculate Linux image builder") -CMD_OPTIONS = [] +CMD_OPTIONS = [{'shortOption':"f", + 'longOption':"force", + 'help':_("no questions during the creating process") + }] USAGE = _("%prog [options] iso|squash") class image_cmd(share_cmd): @@ -55,8 +58,11 @@ class image_cmd(share_cmd): if args and not args[0] in self.commands: self.optobj.error(_("invalid command: '%s' (choose from %s)")% (args[0],", ".join(map(lambda x:"'%s'"%x,self.commands)))) - self.logicObj.clVars.Set('cl_action',args[0],True) + # for work with v param + if args: + self.logicObj.clVars.Set('cl_action',args[0],True) + self.logicObj.clVars.Set('cl_builder_iso_path','/mnt/flash',True) self.optobj.checkVarSyntax(values) return (values, args) @@ -66,9 +72,13 @@ class image_cmd(share_cmd): action[args[0]](options) def makeIso(self,options): - """Set specified kernel to default""" + """Make iso""" + if not self.logicObj.makeIsoImage(options.f): + return False return True def makeSquash(self,options): - """Set specified kernel to default""" + """Make squash (rescratch)""" + if not self.logicObj.makeRescratch(options.f): + return False return True diff --git a/pym/cl_share_cmd.py b/pym/cl_share_cmd.py index c9badb3..466bbb5 100644 --- a/pym/cl_share_cmd.py +++ b/pym/cl_share_cmd.py @@ -19,6 +19,7 @@ import os from cl_print import color_print from cl_utils import _error +from cl_builder import BuilderError # Перевод сообщений для программы from cl_lang import lang @@ -63,6 +64,8 @@ class share_cmd(color_print, _error): k,o,v = val.partition('=') if self.logicObj.clVars.exists(k): if not self.logicObj.clVars.SetWriteVar(k,v): + self.printERROR( + BuilderError().popBuilderErrors().strip()) return False else: self.printERROR(_('variable %s not found')%k) diff --git a/pym/cl_vars_builder.py b/pym/cl_vars_builder.py index 8ee2abc..5741c4a 100644 --- a/pym/cl_vars_builder.py +++ b/pym/cl_vars_builder.py @@ -19,7 +19,7 @@ # select - list of posible values for variable # official - flag, if it is True, then the variable is not printable # printval - print value of variable -from cl_install import __version__, __app__ +from cl_builder import __version__, __app__ class Data: # relative path for apply templates on files of system @@ -74,11 +74,16 @@ class Data: # need perform templates for builder:squahs cl_builder_squash_action = {} + # directory for packing + cl_builder_path = {'mode':'w', + 'value':'/mnt/builder'} + # directory of system for livecd.squashfs - cl_builder_squash_path = {} + cl_builder_squash_path = {'mode':'w', + 'value':"/livecd.squashfs.dir"} # directory for iso building - cl_builder_iso_path = {} + cl_builder_iso_path = {'mode':'w'} # kernel image cl_builder_kernel = {} @@ -110,10 +115,14 @@ class Data: # livecd.squashfs name (may be livecd.squashfs.2 and etc) cl_builder_current_squash = {} + # livecd.squashfs name for remove (may be livecd.squashfs.2 and etc) + cl_builder_remove_squash = {} + # iso image full path cl_builder_image = {} # path which contains images - cl_builder_image_path = {'value':['/var/calculate/remote/linux', - '/var/calculate/linux', + cl_builder_image_path = {'mode':'w', + 'value':['/var/calculate/linux', + '/var/calculate/remote/linux', '/usr/calculate/share/linux']}