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-builder/pym/cl_builder.py

374 lines
14 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.
__version__ = "2.2.0.0"
__app__ = "calculate-builder"
import os
import re
import sys
import traceback
from os import path
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"""
def importBuilder(self, **args):
'''Get variables for builder'''
# section name in calculate.env
envSection = "builder"
# import builder variables
self.importData(envSection, ('cl_vars_builder','cl_fill_builder'))
class cl_builder(color_print):
"""Primary class for image manipulation"""
def __init__(self):
self.clVars = None
self.startMessage = ""
def setNoColor(self):
self.color = False
def initVars(self):
"""Primary initialization of variables"""
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 getFreeFor(self,pathname):
"""Get free for pathname"""
dfProcess = process("/bin/df","-h",pathname)
data = filter(lambda x:x.startswith('/dev'),dfProcess)
if data:
data = filter(lambda x:x,data[0].split())
if len(data)>3:
return data[3]
return "Unknown"
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.printSUCCESS(_("Free disk space for iso building: %s")%
self.getFreeFor(path.dirname(path.normpath(
self.clVars.Get('cl_builder_iso_path')))))
self.printSUCCESS(_("Free disk space for iso image: %s")%
self.getFreeFor(self.clVars.Get('cl_builder_image')))
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")%
self.clVars.Get('cl_builder_iso_path'))
if self.clVars.Get('cl_builder_remove_squash'):
self.printSUCCESS(
_("Follow squash images will be removed: %s\n")%
", ".join(self.clVars.Get('cl_builder_remove_squash')))
else:
self.defaultPrint("\n")
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)
self.clVars.Get('cl_builder_remove_squash')
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)
self.printMessageForTest(_("Removing old images"))
oldImages = map(lambda x:pathJoin(buildDirectory,x),
self.clVars.Get('cl_builder_remove_squash'))
try:
map(lambda x:os.unlink(x),oldImages)
except (Exception,KeyboardInterrupt),e:
raise BuilderError(_("Can not remove old files")+":\n%s"%str(e))
self.printByResult(True)
self.printMessageForTest(_("Performing syncronization"))
processSync = process("/bin/sync")
self.printByResult(processSync.success())
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(_("System building failed"))
return False
self.printSUCCESS(_("System has built successfully"))
return True