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.
1938 lines
82 KiB
1938 lines
82 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.28"
|
|
__app__ = "calculate-assemble"
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
import traceback
|
|
from os import path
|
|
from cl_template import template,iniParser
|
|
from cl_utils import process,pathJoin,getRunCommands,getTupleVersion,isMount,\
|
|
isFstabMount,childMounts,_toUNICODE,cmpVersion, \
|
|
listDirectory, readFile, removeDir, getPkgInstalled, \
|
|
getTupleVersion, isPkgInstalled,reVerSplitToPV
|
|
from subprocess import STDOUT,PIPE
|
|
from cl_print import color_print
|
|
from cl_datavars import DataVars
|
|
from cl_distr import IsoDistributive, DirectoryDistributive, \
|
|
DistributiveError, PartitionDistributive, \
|
|
DistributiveRepository, ArchiveDistributive
|
|
from cl_vars_share import varsShare
|
|
|
|
from cl_lang import lang
|
|
lang().setLanguage(sys.modules[__name__])
|
|
from server.utils import dialogYesNo
|
|
import cl_overriding
|
|
import random
|
|
from shutil import copyfile
|
|
import time
|
|
|
|
def DEBUG(msg):
|
|
if "DEBUG" in os.environ:
|
|
sys.stderr.write("%s\n"%msg)
|
|
sys.stderr.flush()
|
|
|
|
class printNoColor:
|
|
def colorPrint(self,attr,fg,bg,string):
|
|
sys.stdout.write(string)
|
|
|
|
class AssembleError(Exception):
|
|
"""Installation Error"""
|
|
assemble_errors = ""
|
|
|
|
def installExit(self,*args,**kwars):
|
|
raise AssembleError(self.__class__.assemble_errors)
|
|
|
|
def overprintERROR(self,error):
|
|
self.__class__.assemble_errors += str(error) + "\n"
|
|
|
|
def getAssembleErrors(self):
|
|
return self.__class__.assemble_errors
|
|
|
|
def popAssembleErrors(self):
|
|
res = self.__class__.assemble_errors
|
|
self.__class__.assemble_errors = ""
|
|
return res
|
|
|
|
def getOverrideMethods(self):
|
|
return self.installExit, self.overprintERROR
|
|
|
|
cl_overriding.exit, cl_overriding.printERROR = \
|
|
AssembleError().getOverrideMethods()
|
|
|
|
class DataVarsAssemble(DataVars):
|
|
"""Variable class for assemble"""
|
|
|
|
def importAssemble(self, **args):
|
|
'''Get variables for assemble'''
|
|
# section name in calculate.env
|
|
envSection = 'assemble'
|
|
# import assemble variables
|
|
self.importData(envSection, ('cl_vars_assemble','cl_fill_assemble'))
|
|
|
|
class cl_assemble(color_print):
|
|
"""Primary class for assemble actions"""
|
|
# action list for update distributive
|
|
# step - step name
|
|
# args - variable get by clVars and paste to command
|
|
# command - executed command
|
|
# condition - check this package name merged in emerge.log
|
|
# message - Alternate message
|
|
# progname - check by 'which' existing this program
|
|
# hideout - hide stdout
|
|
# foraction - perform only for cl_action == value
|
|
DEFAULT_FORACTION = ('make','syncupdate','update')
|
|
ACTION_LIST = \
|
|
[
|
|
# emerge -e system first
|
|
{'command':'emerge -e system',
|
|
'message':_("First execute '%s'")%'emerge -e system',
|
|
'step':'firstsystem',
|
|
'foraction':('make',)},
|
|
# emerge -e system second
|
|
{'command':'emerge -e system',
|
|
'message':_("Second execute '%s'")%'emerge -e system',
|
|
'step':'secondsystem',
|
|
'foraction':('make',)},
|
|
# emerge world
|
|
{'command':'emerge -e world',
|
|
'step':'rebuildworld',
|
|
'foraction':('make',)},
|
|
{'step':'stagecomplete',
|
|
'foraction':('make',)},
|
|
# update prepareTemplates
|
|
{'command':"prepareTemplates()",
|
|
'foraction':('syncupdate','update','applytemplates'),
|
|
'hideout':True,
|
|
'message':_("Configuring with %s templates")% "assemble"
|
|
},
|
|
{'command':"_migratePortage()",
|
|
'foraction':('syncupdate',),
|
|
'step':"migrate",
|
|
'hideout':True,
|
|
'message':_("Checking portage repository")
|
|
},
|
|
{'command':'eix-sync',
|
|
'progname':'eix-sync',
|
|
'message':_("Updating portages"),
|
|
'hideout':True,
|
|
'step':"eixsync",
|
|
'foraction':('syncupdate',)},
|
|
# try install python
|
|
{'command':'emerge -u python',
|
|
'step':'updatepython',
|
|
'condition':'dev-lang/python',
|
|
'checkcommand':'emerge -uOp python'
|
|
},
|
|
# update python
|
|
{'command':'python-updater',
|
|
'step':'fixpython',
|
|
'condition':'dev-lang/python',
|
|
'progname':'python-updater'},
|
|
# try install perl
|
|
{'command':'emerge -u perl',
|
|
'step':'updateperl',
|
|
'condition':'dev-lang/perl',
|
|
'checkcommand':'emerge -uOp perl'
|
|
},
|
|
# update perl
|
|
{'command':'perl-cleaner all',
|
|
'step':'fixperl',
|
|
'condition':'dev-lang/perl',
|
|
'progname':'perl-cleaner'},
|
|
# install meta package
|
|
{'command':'emerge --noreplace calculate-meta',
|
|
'checkcommand':'find /var/db/pkg/app-misc -name "calculate-meta*"',
|
|
'condition':'^$',
|
|
'step':'meta'},
|
|
# update packages with fix newuse
|
|
#{'command':'emerge -D --newuse world',
|
|
# 'step':'newuse'},
|
|
# update world
|
|
{'command':'emerge -uDN --with-bdeps=y world',
|
|
'step':'update'},
|
|
# depclean
|
|
{'command':'emerge --depclean',
|
|
'step':'depclean'},
|
|
# module rebuild
|
|
{'command':'modulesRebuild()',
|
|
'step':'module',
|
|
'condition':'sys-kernel/.*source.*',
|
|
'message':_("Executing '%s'")%'module-rebuild -X rebuild',
|
|
'progname':'module-rebuild'},
|
|
# xorg module rebuild
|
|
{'command':'emerge @x11-module-rebuild',
|
|
'step':'x11module',
|
|
'condition':'x11-base/xorg-server*'},
|
|
# revdep-rebuild
|
|
{'command':'revdepRebuild()',
|
|
'step':'revdep',
|
|
'condition':'.',
|
|
'message':_("Executing '%s'")%'revdep-rebuild -i',
|
|
'progname':'revdep-rebuild'},
|
|
# emerge @preserved-rebuild
|
|
{'command':'emerge @preserved-rebuild',
|
|
'step':'presrebuild',
|
|
'condition':'.'
|
|
},
|
|
# prelink all packages
|
|
{'command':'prelink -afmR',
|
|
'step':'prelink',
|
|
'hideout':True,
|
|
'condition':'.',
|
|
'progname':'prelink'},
|
|
# get propreitary drivers
|
|
{'command':'fetchDrivers()',
|
|
'step':'fetchdrivers',
|
|
'message':_("Fetching %s")%'video drivers'},
|
|
# emerge all nvidia-drivers
|
|
#{'command':'makeNvidiaDrivers()',
|
|
# 'step':'nvidia',
|
|
# 'hideout':True,
|
|
# 'message':_("Assembling %s")%'nvidia-drivers'},
|
|
# binary cleaning
|
|
{'command':'binaryCleaning()',
|
|
'step':'binclean',
|
|
'message':_("Cleaning the binary repository"),
|
|
'hideout':True
|
|
},
|
|
# creating mask,unmask list
|
|
#{'command':'createMaskUnmaskList()',
|
|
# 'step':'maskunmask',
|
|
# 'message':_("Creating mask/unmask/use lists"),
|
|
# 'hideout':True
|
|
#},
|
|
# update eix base
|
|
{'command':'eix-update',
|
|
'step':'eixupdate',
|
|
'hideout':True,
|
|
'progname':'eix-update'},
|
|
{'command':'eselect news read new',
|
|
'step':'readnews',
|
|
'message':_("Reading news"),
|
|
'progname':'eselect'},
|
|
{'command':"checkDowngrades()",
|
|
'message':_("Checking downgrades"),
|
|
'step':'showdowngrade',
|
|
'progname':'eix'}]
|
|
|
|
reVerSplit = re.compile(r"^(.*?)-(([^-]+?)(?:-(r\d+))?)(?:.(tbz2))?$",re.S)
|
|
|
|
def __init__(self):
|
|
self.clVars = None
|
|
self.startMessage = ""
|
|
self.lenStartMessage = 0
|
|
self.clTempl = None
|
|
self.force = False
|
|
self.mainAction = None
|
|
self.assembleEnvFile = '/etc/calculate/assemble.env'
|
|
self.assemblePath = None
|
|
|
|
def setNoColor(self):
|
|
self.color = False
|
|
|
|
def initVars(self):
|
|
"""Primary initialization of variables"""
|
|
self.clVars = DataVarsAssemble()
|
|
self.clVars.importAssemble()
|
|
self.clVars.flIniFile()
|
|
|
|
def applyConfigureTemplates(self,directory,message=None):
|
|
"""Apply templates for root of system."""
|
|
if message:
|
|
self.printMessageForTest(message)
|
|
self.clVars.Set("cl_chroot_path",directory, True)
|
|
self.clTempl = template(self.clVars)
|
|
dirsFiles = self.clTempl.applyTemplates()
|
|
self.clTempl.closeFiles()
|
|
if self.clTempl.getError():
|
|
raise AssembleError(self.clTempl.getError())
|
|
else:
|
|
return dirsFiles
|
|
|
|
def printMessageForTest(self, message, lenMsg=False):
|
|
"""Print waiting message and OK or Error by func result"""
|
|
self.printByResult(True)
|
|
message = "%s ..." % message
|
|
self.printSUCCESS(message,printBR=False)
|
|
self.startMessage = message
|
|
if lenMsg:
|
|
self.lenStartMessage = lenMsg
|
|
else:
|
|
self.lenStartMessage = self.lenString(self.startMessage)
|
|
|
|
def printSkip(self, string, offsetL=0, printBR=True):
|
|
"""print skip"""
|
|
self._printSysOut = sys.stdout
|
|
self.printLine((('', string),),
|
|
(('blueBr','['),
|
|
('yellowBr',' skipped '),
|
|
('blueBr',']'),
|
|
), offsetL, printBR)
|
|
|
|
|
|
def printOnlyNotOK(self, string, offsetL=0, printBR=True):
|
|
"""Print for error"""
|
|
self._printSysOut = sys.stdout
|
|
self.printLine((('', string),),
|
|
(('blueBr','['),
|
|
('redBr',' !! '),
|
|
('blueBr',']'),
|
|
), offsetL, printBR)
|
|
|
|
def printByResult(self,result=True,failMessage=None,skip=False):
|
|
if self.startMessage:
|
|
offset = 3
|
|
if skip:
|
|
self.printSkip(" ", self.lenStartMessage + offset)
|
|
elif result:
|
|
self.printOnlyOK(" ", self.lenStartMessage + offset)
|
|
else:
|
|
self.printOnlyNotOK(" ", self.lenStartMessage + offset)
|
|
if failMessage:
|
|
self.printERROR(failMessage)
|
|
self.startMessage = ""
|
|
self.lenStartMessage = 0
|
|
|
|
def setAction(self,action):
|
|
if action == "break":
|
|
self.clVars.Set("cl_action","break",True)
|
|
elif action == "make":
|
|
self.clVars.Set("cl_action","make",True)
|
|
elif action == "update":
|
|
self.clVars.Set("cl_action","update",True)
|
|
elif action == "syncupdate":
|
|
self.clVars.Set("cl_action","syncupdate",True)
|
|
elif action == "dependence":
|
|
self.clVars.Set("cl_action","dependence",True)
|
|
elif action == "applytemplates":
|
|
self.clVars.Set("cl_action","applytemplates",True)
|
|
else:
|
|
self.clVars.Set("cl_action","configure",True)
|
|
|
|
def __profileShortname(self,profilename):
|
|
return profilename.rpartition('/profiles/')[2]
|
|
|
|
def printInfo(self):
|
|
self.printSUCCESS(_("Preparing for assemble") + " Calculate Linux")
|
|
self.defaultPrint("%s\n"%_("System information"))
|
|
subname = self.clVars.Get('os_assemble_linux_subname')
|
|
subname = (" %s"%subname) if subname else ""
|
|
self.printSUCCESS(_("System profile")+": %s"%
|
|
self.__profileShortname(
|
|
self.clVars.Get('os_assemble_system_profile')))
|
|
self.printSUCCESS(_("System to be built")+": %s"%
|
|
self.clVars.Get('os_assemble_linux_name')+subname)
|
|
if self.clVars.Get('os_assemble_linux_ver'):
|
|
self.printSUCCESS(_("System version")+": %s"%
|
|
self.clVars.Get('os_assemble_linux_ver'))
|
|
self.printSUCCESS(_("Hardware type")+": %s"%
|
|
self.clVars.Get('os_assemble_arch_machine'))
|
|
if path.isdir(self.clVars.Get('os_assemble_root_dev')):
|
|
self.printSUCCESS(_("Directory for assembling: %s")%
|
|
self.clVars.Get('os_assemble_root_dev'))
|
|
else:
|
|
self.printSUCCESS(_("Partition for assemble: %s")%
|
|
self.clVars.Get('os_assemble_root_dev'))
|
|
self.printSUCCESS(_("File system: %s")%
|
|
self.clVars.Get('os_assemble_root_format'))
|
|
if self.clVars.Get('cl_assemble_sync'):
|
|
self.printSUCCESS(_("Portage mirror: %s")%
|
|
self.clVars.Get('cl_assemble_sync'))
|
|
self.printSUCCESS(_("Stage for assembling: %s")%
|
|
(self.clVars.Get('cl_assemble_image') or _("none")))
|
|
if self.clVars.Get('cl_assemble_image_type') == "stage" and \
|
|
self.clVars.Get('cl_assemble_branch') == '':
|
|
self.printSUCCESS(_("Portage snapshot for assemble: %s")%
|
|
(self.clVars.Get('cl_assemble_snapshot_portage') or _("none")))
|
|
self.defaultPrint("%s\n"%_("Checking up before assemble"))
|
|
|
|
self.defaultPrint("\n")
|
|
|
|
def printConfInfo(self):
|
|
self.defaultPrint("%s\n"%_("System information"))
|
|
subname = self.clVars.Get('os_assemble_linux_subname')
|
|
subname = (" %s"%subname) if subname else ""
|
|
self.printSUCCESS(_("System profile")+": %s"%
|
|
self.__profileShortname(
|
|
self.clVars.Get('os_assemble_system_profile')))
|
|
self.printSUCCESS(_("System to be built")+": %s"%
|
|
self.clVars.Get('os_assemble_linux_name')+subname)
|
|
if self.clVars.Get('os_assemble_linux_ver'):
|
|
self.printSUCCESS(_("System version")+": %s"%
|
|
self.clVars.Get('os_assemble_linux_ver'))
|
|
self.printSUCCESS(_("Hardware type")+": %s"%
|
|
self.clVars.Get('os_assemble_arch_machine'))
|
|
self.printSUCCESS(_("Partition for assemble: %s")%
|
|
self.clVars.Get('os_assemble_root_dev'))
|
|
self.printSUCCESS(_("The system is being assembled in: %s")%
|
|
self.clVars.Get('cl_assemble_path'))
|
|
|
|
self.defaultPrint("\n")
|
|
|
|
def _checkAlreadyAssembling(self,printERROR=True):
|
|
section = self.__sectionName()
|
|
if not section in self.clVars.Get('cl_assemble_distro'):
|
|
if printERROR:
|
|
self.printERROR(
|
|
_("System with '%s' profile not ready for assemble")%
|
|
self.__profileShortname(
|
|
self.clVars.Get('os_assemble_system_profile')))
|
|
self.printERROR(
|
|
_("Your system must be configured before you do this")+".")
|
|
self.printERROR(_("Execute with option")+' "--configure".')
|
|
if self.clVars.Get('cl_assemble_distro'):
|
|
self.defaultPrint("\n"+_("Systems prepared for assemble")+
|
|
":\n")
|
|
for system in self.clVars.Get('cl_assemble_distro'):
|
|
self.printSUCCESS(self.__profileShortname(system))
|
|
self.removeDistroInfo()
|
|
return False
|
|
return True
|
|
|
|
def preassembleCheckups(self):
|
|
rsyncServer = self.clVars.Get('cl_assemble_sync')
|
|
self.setSyncMirror(rsyncServer)
|
|
if re.match(r'^i.86$',self.clVars.Get('os_arch_machine'),re.S):
|
|
if self.clVars.Get('os_assemble_arch_machine') in ('x86_64','ia64'):
|
|
self.printERROR(
|
|
_("Unable to assemble the system %(what)s from %(from)s")%
|
|
{'what':self.clVars.Get('os_assemble_arch_machine'),
|
|
'from':self.clVars.Get('os_arch_machine')})
|
|
return False
|
|
dev = self.clVars.Get('os_assemble_root_dev')
|
|
mp = isFstabMount(dev)
|
|
if mp:
|
|
self.printERROR(
|
|
_("'%(dev)s' is used as '%(mp)s' on your current system")%
|
|
{'dev':dev,'mp':mp})
|
|
return False
|
|
if self._checkAlreadyAssembling(printERROR=False):
|
|
dev = self.readEnv('os_assemble_root_dev') or dev
|
|
mp = isMount(dev)
|
|
self.printERROR(
|
|
_("Distribution with profile %(profile)s is being assembled"
|
|
" in '%(dir)s' now")%
|
|
{'profile':self.__profileShortname(
|
|
self.clVars.Get('os_assemble_system_profile')),
|
|
'dir':mp})
|
|
return False
|
|
mp = isMount(dev)
|
|
if mp:
|
|
self.printERROR(_("'%(dev)s' already mounted to '%(mp)s'")%
|
|
{'dev':dev,'mp':mp})
|
|
return False
|
|
if not self.clVars.Get('cl_assemble_image'):
|
|
self.printERROR(_("Base stage not found. Try "
|
|
"to change '--source'."))
|
|
return False
|
|
return True
|
|
|
|
def _askUser(self,force,question):
|
|
"""Ask user about continue"""
|
|
if not force:
|
|
dialogMessage = question + " (yes/no)"
|
|
try:
|
|
dialogRes = dialogYesNo(dialogMessage)
|
|
except KeyboardInterrupt:
|
|
self.defaultPrint("\n")
|
|
raise KeyboardInterrupt
|
|
if dialogRes in (None,False):
|
|
return False
|
|
return True
|
|
|
|
# configure helper functions
|
|
def _unpackPortage(self):
|
|
"""Unpack portage"""
|
|
stageName = self.clVars.Get('cl_assemble_snapshot_portage')
|
|
self.printMessageForTest(_("Unpacking portages"))
|
|
if stageName:
|
|
portageSources = ArchiveDistributive(stageName)
|
|
portageTarget = DirectoryDistributive(
|
|
path.join(self.assemblePath,"usr"))
|
|
portageTarget.installFrom(portageSources)
|
|
self.printByResult(True)
|
|
else:
|
|
self.printByResult(skip=True)
|
|
|
|
def _formatAndUnpackStage(self):
|
|
"""Format partition for assemble and unpack stage"""
|
|
self.printMessageForTest(_("Formatting the partition"))
|
|
self.saveVars('os_assemble_root_dev')
|
|
self.targetDistr.performFormat()
|
|
|
|
self.printMessageForTest(_("Unpacking the stage image to target"))
|
|
self.saveVars('os_assemble_root_dev')
|
|
self.targetDistr.installFrom(self.sourceDistr)
|
|
self.assemblePath = \
|
|
self.targetDistr.convertToDirectory().getDirectory()
|
|
self.clVars.Set('cl_assemble_path', self.assemblePath, True)
|
|
self.saveVars('os_assemble_linux_shortname',
|
|
'os_assemble_linux_ver',
|
|
'os_assemble_arch_machine',
|
|
'cl_assemble_image',
|
|
'os_assemble_root_dev',
|
|
'cl_assemble_path',
|
|
'cl_assemble_sync',
|
|
'cl_assemble_branch',
|
|
'cl_assemble_buildpkg_set',
|
|
'cl_assemble_pkgdir')
|
|
|
|
def _getTarget(self):
|
|
rootPartdev = self.clVars.Get('os_assemble_root_dev')
|
|
formatId = PartitionDistributive.formatId
|
|
fileSystem = self.clVars.Get('os_assemble_root_format')
|
|
if rootPartdev.startswith('/dev'):
|
|
return PartitionDistributive(rootPartdev,
|
|
mdirectory=self.clVars.Get('cl_assemble_path'),
|
|
check=True, fileSystem=fileSystem, isFormat=True,
|
|
systemId=formatId.get(fileSystem,"83"),
|
|
flagRemoveDir=False,
|
|
rootLabel="%s-%s"%
|
|
(self.clVars.Get('os_assemble_linux_shortname'),
|
|
self.clVars.Get('os_assemble_linux_ver')))
|
|
else:
|
|
return DirectoryDistributive(rootPartdev,
|
|
mdirectory=self.clVars.Get('cl_assemble_path'))
|
|
|
|
def _prepareMount(self):
|
|
"""Mount /proc,/sys, remote, /dev to chroot"""
|
|
mountResources = (("/dev",None,None),
|
|
("/dev/shm",None,None),
|
|
("/dev/pts",None,None),
|
|
(None,"-t proc","/proc"),
|
|
(None,"-t sysfs","/sys"),
|
|
("/var/calculate/remote",None,None))
|
|
for source,opts,target in mountResources:
|
|
opts = opts or "-o bind"
|
|
target = target or source
|
|
self.printMessageForTest(_("Mounting %s")%(source or target))
|
|
target = pathJoin(self.assemblePath,target)
|
|
if not path.exists(target):
|
|
os.makedirs(target,mode=0755)
|
|
if source == isMount(target):
|
|
continue
|
|
args = ["mount"]+opts.split()+[str(source).lower(),target]
|
|
mountProcess = process(*args)
|
|
if mountProcess.failed():
|
|
raise AssembleError(_("Failed to mount %(from)s to %(to)s")%
|
|
{'from':source,'to':target})
|
|
if self.targetDistr:
|
|
DirectoryDistributive(target,parent=self.targetDistr)
|
|
self.printByResult(True)
|
|
|
|
def _migratePortage(self):
|
|
if self.clVars.Get('cl_assemble_branch'):
|
|
if not isPkgInstalled('dev-vcs/git'):
|
|
self.printMessageForTest(_("Installing %s")%'dev-vcs/git')
|
|
self.runChroot("emerge -1 git")
|
|
portagePath = pathJoin(self.assemblePath,'usr/portage')
|
|
gitConfig = pathJoin(portagePath, '.git/config')
|
|
# check for repository contains .git and
|
|
# this git from cl_assemble_sync url
|
|
reUrl = re.compile('url\s*=\s*(.*)')
|
|
gitUrl = reUrl.search(readFile(gitConfig))
|
|
# need remove portage and reget from sync address
|
|
self.printMessageForTest(_("Fetching portages"))
|
|
if not gitUrl or \
|
|
gitUrl.group(1).strip() != self.clVars.Get('cl_assemble_sync'):
|
|
if path.exists(portagePath):
|
|
removeDir(portagePath)
|
|
getPortage = "git clone --depth 1 -n {gitrep} {portage}".format(
|
|
gitrep=self.clVars.Get('cl_assemble_sync'),
|
|
portage='/usr/portage')
|
|
self.runChroot(getPortage)
|
|
else:
|
|
getPortage = "cd {portage};git fetch".format(
|
|
gitrep=self.clVars.Get('cl_assemble_sync'),
|
|
portage='/usr/portage')
|
|
self.runChroot(getPortage)
|
|
updateBranch= "cd {portage};git checkout {branch}".format(
|
|
portage='/usr/portage',
|
|
branch=self.clVars.Get('cl_assemble_branch'))
|
|
self.runChroot(updateBranch)
|
|
|
|
portagePkg = getPkgInstalled('sys-apps/portage',
|
|
prefix=self.assemblePath)
|
|
portageMinVer = getTupleVersion('2.2.0_alpha72')
|
|
if portagePkg and \
|
|
getTupleVersion(portagePkg[0]['PVR']) < portageMinVer:
|
|
lastEbuild = \
|
|
sorted(
|
|
map(lambda x:(x['P'],
|
|
getTupleVersion(x['PVR'])),
|
|
map(lambda x:reVerSplitToPV(x),
|
|
filter(lambda x:x.endswith('ebuild'),
|
|
listDirectory(pathJoin(self.assemblePath,
|
|
'usr/portage/sys-apps/portage'))
|
|
))),key=lambda x:x[1])
|
|
if len(lastEbuild) > 1:
|
|
lastEbuild = lastEbuild[-2][0]
|
|
else:
|
|
return
|
|
self.printMessageForTest(_("Installing %s")%"portage")
|
|
emergePortage = \
|
|
'ebuild /usr/portage/sys-apps/portage/%s digest merge'% \
|
|
lastEbuild
|
|
self.runChroot(emergePortage)
|
|
restoreManifest = \
|
|
'cd /usr/portage;git checkout sys-apps'
|
|
self.runChroot(restoreManifest)
|
|
else:
|
|
portagePath = pathJoin(self.assemblePath,'usr/portage')
|
|
gitConfig = pathJoin(portagePath, '.git/config')
|
|
if path.exists(gitConfig):
|
|
removeDir(portagePath)
|
|
if self.clVars.Get('cl_assemble_branch') in ('master','update'):
|
|
pathOverlay = pathJoin(self.assemblePath,'var/lib/layman/calculate')
|
|
if path.exists(pathOverlay):
|
|
updateBranch= \
|
|
"cd {portage};git pull;git checkout {branch}".format(
|
|
portage='/var/lib/layman/calculate',
|
|
branch=self.clVars.Get('cl_assemble_branch'))
|
|
self.runChroot(updateBranch)
|
|
|
|
def _updatePackages(self):
|
|
"""Update portage and calculate overlay"""
|
|
self._migratePortage()
|
|
emergeSync = "emerge --sync"
|
|
self.printMessageForTest(_("Updating portages"))
|
|
self.runChroot(emergeSync)
|
|
|
|
emergeLayman = "USE='git' emerge layman"
|
|
self.printMessageForTest(_("Installing %s")%"layman")
|
|
self.runChroot(emergeLayman)
|
|
|
|
# stage3 contains python-2.7 without USE="xml" need for layman
|
|
emergePython = "USE='xml' emerge -1 python:2.7"
|
|
self.printMessageForTest(_("Installing %s")%"python:2.7")
|
|
self.runChroot(emergePython)
|
|
self.printMessageForTest(_("Set %s as default")%"python:2.7")
|
|
self.runChroot('eselect python set python2.7')
|
|
|
|
self.printMessageForTest(_("Loading calculate overlay"))
|
|
if filter(lambda x:"calculate" in x,self.runChroot("layman -l")):
|
|
self.runChroot("layman -s calculate")
|
|
else:
|
|
self.runChroot("layman -L")
|
|
self.runChroot("layman -a calculate")
|
|
if self.clVars.Get('cl_assemble_branch') in ('master','update'):
|
|
updateBranch= "cd {portage};git checkout {branch}".format(
|
|
portage='/var/lib/layman/calculate',
|
|
branch=self.clVars.Get('cl_assemble_branch'))
|
|
self.runChroot(updateBranch)
|
|
|
|
def _updateMan(self):
|
|
"""Remove man, install man-db"""
|
|
self.printMessageForTest(
|
|
_("Installing man-db"))
|
|
if "calculate" in self.clVars.Get('os_assemble_system_profile'):
|
|
removeMan = "CLEAN_DELAY=0 emerge -C --backtrack=0 " \
|
|
"sys-apps/man"
|
|
self.runChroot(removeMan)
|
|
self.runChroot("emerge sys-apps/man-db")
|
|
self.printByResult(True)
|
|
else:
|
|
self.printByResult(skip=True)
|
|
|
|
def _updateBaselayout(self):
|
|
"""Remove baselayout, update openrc"""
|
|
self.printMessageForTest(
|
|
_("Updating baselayout and installing openrc"))
|
|
if "calculate" in self.clVars.Get('os_assemble_system_profile'):
|
|
removeBaselayout = "CLEAN_DELAY=0 emerge -C --backtrack=0 " \
|
|
"sys-apps/baselayout sys-apps/sysvinit"
|
|
self.runChroot(removeBaselayout)
|
|
self._removeFiles("/etc/init.d/depscan.sh",
|
|
"/etc/init.d/functions.sh",
|
|
"/etc/init.d/runscript.sh",
|
|
prefix=self.assemblePath,
|
|
errormsg=_("Cannot remove files from baselayout"))
|
|
self.runChroot("emerge sys-apps/openrc sys-apps/sysvinit "
|
|
"sys-fs/udev sys-fs/e2fsprogs")
|
|
self._removeFiles("/etc/runlevels/boot/network",
|
|
prefix=self.assemblePath)
|
|
self.printByResult(True)
|
|
else:
|
|
self.printByResult(skip=True)
|
|
|
|
def prepareTemplates(self,message=False,changeAction=False):
|
|
"""Apply prepare templates"""
|
|
if changeAction:
|
|
self.clVars.Set('cl_action',"configure",True)
|
|
if message == True:
|
|
message = _("Configuring with %s templates")% "assemble/prepare"
|
|
self.applyConfigureTemplates(self.assemblePath,message)
|
|
if changeAction and self.mainAction:
|
|
self.clVars.Set('cl_action',self.mainAction,True)
|
|
self.printByResult(True)
|
|
|
|
def setupTemplates(self,message=False,changeAction=False):
|
|
"""Apply setup templates"""
|
|
if changeAction:
|
|
self.clVars.Set('cl_action',"setup",True)
|
|
if message == True:
|
|
message = _("Configuring with %s templates")% "assemble/setup"
|
|
self.applyConfigureTemplates(self.assemblePath,message)
|
|
if changeAction and self.mainAction:
|
|
self.clVars.Set('cl_action',self.mainAction,True)
|
|
self.printByResult(True)
|
|
|
|
def configureFunc(self,force=False,nounmount=False):
|
|
"""Function of configure partition for assembling by make"""
|
|
# print info
|
|
self.printInfo()
|
|
if not self.preassembleCheckups():
|
|
return False
|
|
self.targetDistr = self._getTarget()
|
|
distName = self.clVars.Get('cl_assemble_image')
|
|
if distName and self.targetDistr:
|
|
distRep = DistributiveRepository()
|
|
self.sourceDistr = distRep.getDistributiveByFile(distName)
|
|
if not self._askUser(force, _("Continue system assemble")):
|
|
self.printERROR(_("Assemble interrupted"))
|
|
self.removeDistroInfo()
|
|
return False
|
|
self.writeVar('cl_assemble_make','configure')
|
|
# test /mnt
|
|
mntpath = '/mnt'
|
|
if not os.access(mntpath,os.W_OK):
|
|
raise AssembleError(
|
|
_("Unable to create the directory in '%s'")%mntpath)
|
|
# format partion
|
|
self._formatAndUnpackStage()
|
|
if nounmount:
|
|
self.targetDistr = None
|
|
|
|
pathAppMisc = pathJoin(self.assemblePath,'/var/db/pkg/app-misc')
|
|
metaPackage = self.clVars.Get('cl_assemble_meta').rpartition('/')[2]
|
|
|
|
if not isinstance(self.sourceDistr,IsoDistributive) and \
|
|
self.clVars.Get('cl_assemble_branch') == '':
|
|
self._unpackPortage()
|
|
|
|
self._prepareMount()
|
|
self.prepareTemplates(True,changeAction=True)
|
|
|
|
if path.exists(pathAppMisc) and metaPackage and \
|
|
filter(lambda x:metaPackage in x, os.listdir(pathAppMisc)):
|
|
self.setupTemplates(True,changeAction=True)
|
|
self.writeVar('cl_assemble_make','')
|
|
return True
|
|
|
|
self._updatePackages()
|
|
self.setupTemplates(True,changeAction=True)
|
|
|
|
self.printMessageForTest(
|
|
_("Enabling calculate-install to configure packages"))
|
|
if "calculate" in self.clVars.Get('os_assemble_system_profile'):
|
|
# emerge sys-apps/iproute2, because calculate-install
|
|
# need emerge with USE="minimal", but emerging
|
|
# will install iproute2 with USE="minimal" also
|
|
self.runChroot("emerge -1 sys-apps/iproute2")
|
|
self.runChroot("USE='minimal -pxe' emerge "
|
|
'sys-apps/calculate-install')
|
|
self.runChroot("cl-install --install")
|
|
else:
|
|
self.printByResult(skip=True)
|
|
|
|
emergePortage = "emerge sys-apps/portage"
|
|
self.printMessageForTest(_("Installing %s")%"portage")
|
|
self.runChroot(emergePortage)
|
|
|
|
if not isinstance(self.sourceDistr,IsoDistributive):
|
|
self.printMessageForTest(_("Receiving kernel sources"))
|
|
self.runChroot('USE="-vmlinuz" emerge '
|
|
"sys-kernel/calculate-sources")
|
|
|
|
if not isinstance(self.sourceDistr,IsoDistributive):
|
|
emergeV86d = "emerge sys-apps/v86d"
|
|
self.printMessageForTest(_("Installing %s")%"v86d")
|
|
self.runChroot(emergeV86d)
|
|
|
|
#if not isinstance(self.sourceDistr,IsoDistributive):
|
|
# self._updateBaselayout()
|
|
if self.clVars.Get('os_assemble_linux_system') == "server" or \
|
|
self.clVars.Get('os_assemble_linux_shortname') != "CLS":
|
|
self._removeFiles("/etc/init.d/net.eth0",
|
|
prefix=self.assemblePath)
|
|
if not isinstance(self.sourceDistr,IsoDistributive):
|
|
self._updateMan()
|
|
|
|
self.setupTemplates(True,changeAction=True)
|
|
self.printMessageForTest(_("Executing '%s'")%"etc-update")
|
|
self.runChroot("OVERWRITE_ALL='yes' etc-update")
|
|
|
|
if not isinstance(self.sourceDistr,IsoDistributive):
|
|
if self.clVars.Get('os_assemble_linux_system')=='desktop':
|
|
self.groupAdd(35,"games")
|
|
self.groupAdd(440,"plugdev")
|
|
self.groupAdd(441,"scanner")
|
|
if self.clVars.Get('os_assemble_linux_shortname')=='CDS':
|
|
self.userAdd(100,"p2p",mode=0700,chown=(100,0),
|
|
home="/home/p2p",groups=["100","wheel"],
|
|
comment="added by Calculate for p2p",
|
|
shell="/bin/bash",prefix=self.assemblePath)
|
|
|
|
self.writeVar('cl_assemble_make','')
|
|
return True
|
|
return False
|
|
|
|
def userAdd(self,userid,username,mode=0755,chown=(0,0),home=None,
|
|
groups=[],comment="",shell="/bin/bash",prefix="/"):
|
|
"""Check exists user and create new"""
|
|
if self.runChroot("id %s"%username,raiseError=False).failed():
|
|
self.printMessageForTest(
|
|
_("Creating %(user)s (%(id)d) user")%
|
|
{'user':username,'id':userid})
|
|
command = "useradd -u %d %s"%(userid,username)
|
|
if groups:
|
|
command += " -g %s"%groups[0]
|
|
if len(groups)>1:
|
|
command += " -G %s"%",".join(groups[1:])
|
|
if comment:
|
|
command += " -c '%s'"%comment
|
|
if shell:
|
|
command += " -s %s"%shell
|
|
self.runChroot(command)
|
|
try:
|
|
os.makedirs(pathJoin(prefix,home),mode=mode)
|
|
os.chown(pathJoin(prefix,home),chown[0],chown[1])
|
|
except (OSError,IOError),e:
|
|
raise AssembleError(
|
|
_("Failed to create the home directory for %s")
|
|
%username)
|
|
|
|
def groupAdd(self,groupid,groupname):
|
|
"""Check exists group and create new"""
|
|
if self.runChroot("groupmems -l -g %s"
|
|
%groupname,raiseError=False).failed():
|
|
self.printMessageForTest(
|
|
_("Creating %(name)s (%(id)d) group")%
|
|
{'name':groupname,'id':groupid})
|
|
self.runChroot("groupadd -g %d %s"%(groupid,groupname))
|
|
self.printByResult(True)
|
|
|
|
def _removeFiles(self,*files,**kwarg):
|
|
"""Remove files specified by files list"""
|
|
prefix = kwarg.get("prefix","/")
|
|
errormsg = kwarg.get("errormsg",None)
|
|
try:
|
|
rmFile = ""
|
|
for fileName in files:
|
|
rmFile = pathJoin(prefix,fileName)
|
|
if path.lexists(rmFile):
|
|
os.unlink(rmFile)
|
|
except (OSError,IOError),e:
|
|
if errormsg is None:
|
|
raise AssembleError(_("Cannot remove '%s'")%rmFile)
|
|
else:
|
|
raise AssembleError(errormsg)
|
|
|
|
def _getCommand(self,commandlist):
|
|
def decodeCmd(x):
|
|
x = x.rpartition(";")[2]
|
|
if " " in x:
|
|
return '"%s"'%x
|
|
else:
|
|
return x
|
|
return " ".join(map(decodeCmd,commandlist))
|
|
|
|
def setSyncMirror(self,mirror):
|
|
"""Set sync mirror"""
|
|
reMirror = re.compile("^(rsync:|git:)?/?/?([^:]+)$",re.S)
|
|
res = reMirror.search(mirror)
|
|
if res:
|
|
if res.groups()[0] == "git:":
|
|
self.clVars.Set('cl_assemble_sync',"git://%s"%res.groups()[1],True)
|
|
else:
|
|
self.clVars.Set('cl_assemble_sync',"//%s"%res.groups()[1],True)
|
|
self.clVars.Set('cl_assemble_branch','',True)
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def runChroot(self,command,raiseError=True,showProcess=False,joinErr=False):
|
|
"""Run command in chroot specified by cl_assemble_path"""
|
|
try:
|
|
if showProcess:
|
|
IOval = None
|
|
else:
|
|
IOval = PIPE
|
|
if joinErr:
|
|
ERRval = STDOUT
|
|
else:
|
|
ERRval = IOval
|
|
envdict = {'CHROOT':"on"}
|
|
envdict.update(os.environ)
|
|
needAsk = self.clVars.Get('cl_assemble_ask_set') == "on"
|
|
if "emerge " in command:
|
|
command = "env-update &>/dev/null;" \
|
|
"source /etc/profile &>/dev/null;%s"%command
|
|
if showProcess and needAsk:
|
|
command = command.replace("emerge ","emerge -a ")
|
|
commandLine = ["chroot",self.clVars.Get('cl_assemble_path'),
|
|
"/bin/bash","-c",command]
|
|
curarch = self.clVars.Get('os_arch_machine')
|
|
buildarch = self.clVars.Get('os_assemble_arch_machine')
|
|
if curarch != buildarch:
|
|
if buildarch == "i686":
|
|
commandLine = ["linux32"] + commandLine
|
|
if showProcess and needAsk:
|
|
chrootCommand = process(*commandLine,stderr=ERRval,
|
|
stdin=None,stdout=IOval,envdict=envdict)
|
|
else:
|
|
chrootCommand = process(*commandLine,stderr=ERRval,
|
|
stdout=IOval,envdict=envdict)
|
|
DEBUG(self._getCommand(chrootCommand.command))
|
|
if raiseError and chrootCommand.failed():
|
|
raise AssembleError(
|
|
_("An error occurred when executing the command")+
|
|
":\n %s"%self._getCommand(chrootCommand.command))
|
|
except KeyboardInterrupt:
|
|
chrootCommand.kill()
|
|
self.defaultPrint("\b\b")
|
|
raise AssembleError(
|
|
_("Interrupted when executing the command")+
|
|
":\n %s"%self._getCommand(chrootCommand.command))
|
|
return chrootCommand
|
|
|
|
def configureSystem(self,force,nounmount):
|
|
"""Unpack stage or cls|css and prepare for assemble"""
|
|
self.msgOperationComplete = ""
|
|
self.msgOperationFailed = \
|
|
_("Failed to prepare the system for assemble")
|
|
if not self._pidCheck():
|
|
return False
|
|
res = self.make(self.configureFunc,force,nounmount)
|
|
if res:
|
|
self.printSUCCESS(
|
|
_("System prepared for assemble in %s")%
|
|
self.clVars.Get('cl_assemble_path')+"!")
|
|
self.printSUCCESS(_("For furhter build, use the 'cl-make' command"))
|
|
return res
|
|
|
|
def breakFunc(self,force):
|
|
mp = self.clVars.Get('cl_assemble_path')
|
|
rootPartdev = self.clVars.Get('os_assemble_root_dev')
|
|
if not self._checkAlreadyAssembling():
|
|
return False
|
|
self.printSUCCESS(_("Assemble interrupted") + " Calculate Linux")
|
|
self.printConfInfo()
|
|
if not self._askUser(force, _("Interrupt system assemble")):
|
|
self.printERROR(_("Assemble resumed"))
|
|
return False
|
|
if mp:
|
|
mps = filter(lambda x:x!=mp,map(lambda x:x[1],childMounts(mp)))
|
|
for target in sorted(mps, reverse=True):
|
|
self.printMessageForTest(_("Unmounting %s")%(target[len(mp):]))
|
|
umountProcess = process("umount",target)
|
|
if umountProcess.failed():
|
|
raise AssembleError(_("Cannot unmount %s")%target)
|
|
self.printByResult(True)
|
|
self.targetDistr = PartitionDistributive(rootPartdev,
|
|
mdirectory='/mnt/builder',flagRemoveDir=False)
|
|
dd = DirectoryDistributive(mp,parent=self.targetDistr)
|
|
return True
|
|
|
|
def checkDependence(self):
|
|
rootPartdev = self.clVars.Get('os_assemble_root_dev')
|
|
mp = isMount(rootPartdev)
|
|
if not self._checkAlreadyAssembling():
|
|
return False
|
|
self.printSUCCESS(_("Checking dependencies of %s assemble")
|
|
% "Calculate Linux")
|
|
self.printConfInfo()
|
|
|
|
command = "emerge -puNv %s %s"%(self.clVars.Get('cl_assemble_meta'),
|
|
"world")
|
|
self.printSUCCESS(_("Checking dependencies")+ " ...")
|
|
if self.runChroot(command, showProcess=True,
|
|
raiseError=False).success():
|
|
self.printSUCCESS(_("Distribution with profile %(profile)s "
|
|
"is ready for compilation")%
|
|
{'profile':self.__profileShortname(
|
|
self.clVars.Get('os_assemble_system_profile'))}+"!")
|
|
return True
|
|
else:
|
|
self.printSUCCESS(_("Distribution with profile %(profile)s "
|
|
"has unresolved dependencies")%
|
|
{'profile':self.__profileShortname(
|
|
self.clVars.Get('os_assemble_system_profile'))})
|
|
return False
|
|
|
|
def breakAssembling(self,force):
|
|
self.msgOperationComplete = \
|
|
_("System assemble resumed")+"!"
|
|
self.msgOperationFailed = \
|
|
_("Failed to interrupt assemble correctly")
|
|
if not self._pidCheck():
|
|
return False
|
|
return self.make(self.breakFunc,force)
|
|
|
|
def _pidCheck(self):
|
|
"""Check pid for run"""
|
|
if str(os.getpid()) != self.clVars.Get('cl_assemble_pid'):
|
|
self.printERROR(_("Already assembling")+" "+
|
|
self._getNameByAction() + " " +
|
|
_("of distribution with profile '%(profile)s'")%
|
|
{'profile':self.__profileShortname(
|
|
self.clVars.Get('os_assemble_system_profile'))})
|
|
return False
|
|
else:
|
|
self.saveVars('cl_assemble_pid')
|
|
return True
|
|
|
|
def makeSystem(self,force):
|
|
self.msgOperationComplete = \
|
|
_("System successfully assembled")+"!"
|
|
self.msgOperationFailed = \
|
|
_("System assemble failed")
|
|
if not self._pidCheck():
|
|
return False
|
|
return self.make(self.makeFunc,force,True,False)
|
|
|
|
def updateSystem(self,force,withsync=True):
|
|
if self.clVars.Get('cl_action') == "applytemplates":
|
|
self.msgOperationComplete = \
|
|
_("Templates successfully applied")+"!"
|
|
self.msgOperationFailed = \
|
|
_("Failed to apply templates")
|
|
else:
|
|
self.msgOperationComplete = \
|
|
_("System successfully assembled")+"!"
|
|
self.msgOperationFailed = \
|
|
_("System assemble failed")
|
|
if not self._pidCheck():
|
|
return False
|
|
stepWorld = filter(lambda x:x,
|
|
self.clVars.Get('cl_assemble_step_world').split(','))
|
|
imageType = self.clVars.Get('cl_assemble_image_type')
|
|
if imageType == 'stage' and \
|
|
not filter(lambda x:x in ("stagecomplete","finish"),stepWorld):
|
|
self.printERROR(
|
|
_("Unable to update the distribution: assemble not completed"))
|
|
self.printERROR(_("Use '%s' for assemble")%'cl-make -m')
|
|
return False
|
|
return self.make(self.makeFunc,force,False,withsync)
|
|
|
|
def _getNameByAction(self):
|
|
act = self.clVars.Get('cl_assemble_make')
|
|
if act == "configure":
|
|
return _("for configuration")
|
|
elif act == "break":
|
|
return _("for breaking the assemble")
|
|
elif act == "system":
|
|
return _("for compilation of system packages")
|
|
elif act != "":
|
|
return _("for package compilation")
|
|
else:
|
|
return ""
|
|
|
|
def makeFunc(self,force,forcesystem=False,makeSync=True):
|
|
rootPartdev = self.clVars.Get('os_assemble_root_dev')
|
|
mp = isMount(rootPartdev)
|
|
if not self._checkAlreadyAssembling():
|
|
return False
|
|
if forcesystem:
|
|
self.printSUCCESS(_("Compiling %s assemble") % "Calculate Linux")
|
|
else:
|
|
self.printSUCCESS(_("Updating %s assemble") % "Calculate Linux")
|
|
|
|
rsyncServer = self.clVars.Get('cl_assemble_sync')
|
|
self.setSyncMirror(rsyncServer)
|
|
|
|
self.printConfInfo()
|
|
self.defaultPrint("%s\n"%_("Checking up before compilation"))
|
|
|
|
if self.clVars.Get('cl_assemble_make') == 'configure':
|
|
self.printWARNING(_("WARNING") +": " +
|
|
_("assemble configuration was not completed"))
|
|
# if assembling completed (finish in cl_assemble_step_world)
|
|
if "finish" in self.clVars.Get('cl_assemble_step_world'):
|
|
# cancel if action make
|
|
if forcesystem:
|
|
return True
|
|
elif self.clVars.Get('cl_action') != "applytemplates":
|
|
# print warning and drop force option
|
|
self.printWARNING(_("WARNING") +": " +
|
|
_("assemble already finished"))
|
|
# if base stage is stage4(iso) display warning for make
|
|
if self.clVars.Get('cl_assemble_image_type') == 'iso' and \
|
|
forcesystem:
|
|
self.printERROR(_("WARNING") +": " +
|
|
_("system packages will be recompiled"))
|
|
self.defaultPrint("\n")
|
|
self._displayCompileAll(self.clVars.Get('cl_action'),
|
|
self.clVars.Get('cl_assemble_step_world'))
|
|
self.defaultPrint("\n")
|
|
|
|
if not self._askUser(force, _("Continue compiling system packages")):
|
|
self.printERROR(_("Compilation interrupted"))
|
|
return False
|
|
self.mainAction = self.clVars.Get('cl_action')
|
|
if self.mainAction in ('make','update','syncupdate'):
|
|
if not force:
|
|
self.clVars.Set('cl_assemble_ask_set', 'on', True)
|
|
self.assemblePath = self.clVars.Get('cl_assemble_path')
|
|
if "finish" in self.clVars.Get('cl_assemble_step_world'):
|
|
self.writeVar('cl_assemble_step_world','stagecomplete',True)
|
|
if self.clVars.Get('cl_assemble_make') == 'configure':
|
|
self.writeVar('cl_assemble_make','',True)
|
|
makeComplete = False
|
|
baseType = self.clVars.Get('cl_assemble_image_type')
|
|
getMake = lambda : self.clVars.Get('cl_assemble_make')
|
|
while not makeComplete:
|
|
if getMake() in ("world",""):
|
|
self._compileAll(self.mainAction)
|
|
self.writeVar('cl_assemble_make','')
|
|
makeComplete = True
|
|
else:
|
|
self.writeVar('cl_assemble_make','')
|
|
return True
|
|
|
|
def _printCheckExecute(self,command,checkBuild=False,msg=None,
|
|
hideOut=False):
|
|
if self.clVars.Get('cl_assemble_make') \
|
|
and command.startswith("emerge"):
|
|
origCommand = command
|
|
if self.clVars.Get('cl_assemble_skipfirst_set') == "on":
|
|
command = "emerge --resume --skipfirst"
|
|
else:
|
|
command = "emerge --resume"
|
|
msg = (_("Resuming '%(orig)s' by '%(exec)s'")%
|
|
{'orig':origCommand,
|
|
'exec':command})
|
|
else:
|
|
msg = msg or (_("Executing '%s'")%command)
|
|
|
|
self.writeVar('cl_assemble_make','world')
|
|
if checkBuild == False or (type(checkBuild) == str \
|
|
and not self.__isPackageBuilded(re.compile(checkBuild))):
|
|
self.printMessageForTest(msg)
|
|
self.printByResult(True,skip=True)
|
|
else:
|
|
if hideOut:
|
|
self.printMessageForTest(msg)
|
|
else:
|
|
self.printSUCCESS("-"*76)
|
|
self.printSUCCESS(msg + " ...")
|
|
self.printSUCCESS("-"*76)
|
|
if re.search(r"^\w+\(\)$",command,re.S):
|
|
getattr(self,command[:-2])()
|
|
else:
|
|
self.runChroot(command, showProcess=not hideOut)
|
|
self.printByResult(True)
|
|
self.writeVar('cl_assemble_make','')
|
|
|
|
def __isAnyPackageBuilded(self):
|
|
"""Any package was builded (detect by log)"""
|
|
logFile = pathJoin(self.clVars.Get('cl_assemble_path'),
|
|
'/var/log/emerge.log')
|
|
reEmerge = re.compile(r"^\d+:\s*>>>\s*emerge",re.S)
|
|
if not os.access(logFile,os.R_OK):
|
|
return False
|
|
return bool(filter(reEmerge.search,open(logFile,"r")))
|
|
|
|
def __isPackageBuilded(self,package):
|
|
"""'package' was builded (detect by log)"""
|
|
logFile = pathJoin(self.clVars.Get('cl_assemble_path'),
|
|
'/var/log/emerge.log')
|
|
reEmerge = re.compile(r"^\d+:\s*>>>\s*emerge[^/]+\s+(\S+/\S+)")
|
|
if not os.access(logFile,os.R_OK):
|
|
return False
|
|
packageWithVer = map(lambda x:x.groups()[0],
|
|
filter(lambda x:x,
|
|
map(reEmerge.search,
|
|
open(logFile,"r"))))
|
|
if type(package) == re._pattern_type:
|
|
return bool(filter(package.search,packageWithVer))
|
|
else:
|
|
return bool(filter(lambda x:package in x,packageWithVer))
|
|
|
|
def _checkChrootProgram(self,progname):
|
|
"""Check existing program by name"""
|
|
if self.runChroot("which %s"%progname,raiseError=False).failed():
|
|
return False
|
|
return True
|
|
|
|
def _compileAll(self,actionName):
|
|
dontRepeatCompleted = bool(actionName == "make")
|
|
"""World compiling"""
|
|
# try perform each action from action list
|
|
for action in self.ACTION_LIST:
|
|
# if specified "progname" check by which in chroot this prog
|
|
if "progname" in action:
|
|
if not self._checkChrootProgram(action["progname"]):
|
|
continue
|
|
|
|
if not actionName in action.get('foraction',self.DEFAULT_FORACTION):
|
|
continue
|
|
if "command" in action:
|
|
command = action["command"]
|
|
if "args" in action:
|
|
command = command % tuple(map(lambda x:self.clVars.Get(x),
|
|
action["args"]))
|
|
if dontRepeatCompleted and action["step"] in \
|
|
self.clVars.Get('cl_assemble_step_world'):
|
|
continue
|
|
checkBuild = action.get("condition",True)
|
|
if "checkcommand" in action:
|
|
process = \
|
|
self.runChroot(action["checkcommand"],raiseError=False)
|
|
checkBuild = bool(re.search(action.get("condition","."),
|
|
process.read(),re.S))
|
|
self._printCheckExecute(command,checkBuild=checkBuild,
|
|
msg=action.get("message",""),
|
|
hideOut=action.get("hideout",False))
|
|
if "step" in action:
|
|
self._appendToStep("world",action["step"])
|
|
self._appendToStep("world","finish")
|
|
|
|
def _displayCompileAll(self,actionName,stepWorld):
|
|
dontRepeatCompleted = bool(actionName == "make")
|
|
"""World compiling"""
|
|
# try perform each action from action list
|
|
self.defaultPrint(_("The following actions will be performed")+":\n")
|
|
showLegend=False
|
|
for action in self.ACTION_LIST:
|
|
if not "command" in action:
|
|
continue
|
|
# if specified "progname" check by which in chroot this prog
|
|
if not actionName in action.get('foraction',self.DEFAULT_FORACTION):
|
|
continue
|
|
command = action["command"]
|
|
if "args" in action:
|
|
command = command % tuple(map(lambda x:self.clVars.Get(x),
|
|
action["args"]))
|
|
suffix = ""
|
|
if "condition" in action:
|
|
suffix += "*"
|
|
showLegend = True
|
|
if dontRepeatCompleted and action["step"] in stepWorld:
|
|
suffix += " (%s)" % _("done")
|
|
self.printSUCCESS(action.get("message",
|
|
_("Executing '%s'")%command)+ suffix)
|
|
if showLegend:
|
|
self.defaultPrint(
|
|
_("Actions marked with '*' will be performed when needed")+
|
|
".\n")
|
|
|
|
def __sectionName(self):
|
|
"""Get section name of assemble.env by shortname and arch"""
|
|
return self.clVars.Get(
|
|
'os_assemble_system_profile').rpartition('/profiles/')[2]
|
|
|
|
def writeVar(self,varname,varvalue,setvar=True):
|
|
"""Write variable to assemble env file"""
|
|
assembleEnv = iniParser(self.assembleEnvFile)
|
|
if setvar:
|
|
self.clVars.Set(varname,varvalue,True)
|
|
return assembleEnv.setVar(self.__sectionName(),{varname:varvalue})
|
|
|
|
def readEnv(self,varname):
|
|
"""Read variable from assemble env file"""
|
|
assembleEnv = iniParser(self.assembleEnvFile)
|
|
return _toUNICODE(assembleEnv.getVar(self.__sectionName(),
|
|
varname)).encode('utf-8')
|
|
|
|
def saveVars(self,*varsname):
|
|
"""Save vars with it current values"""
|
|
assembleEnv = iniParser(self.assembleEnvFile)
|
|
return assembleEnv.setVar(self.__sectionName(),
|
|
dict(map(lambda x:(x,self.clVars.Get(x)),varsname)))
|
|
|
|
def _cleanEnv(self,assembleEnv):
|
|
"""Clean env, remove empty section, remove empty file"""
|
|
# if file hasn't any section
|
|
if not assembleEnv.getAllSectionNames():
|
|
if not assembleEnv.getAllSectionNames():
|
|
if not assembleEnv.getAllSectionNames():
|
|
os.unlink(self.assembleEnvFile)
|
|
# if env has empty section, then remove it
|
|
elif self.__sectionName() in assembleEnv.getAllSectionNames() and \
|
|
not assembleEnv.getAreaVars(self.__sectionName()):
|
|
assembleEnv.delArea(self.__sectionName())
|
|
|
|
def removeDistroInfo(self):
|
|
assembleEnv = iniParser(self.assembleEnvFile)
|
|
assembleEnv.delArea(self.__sectionName())
|
|
self._cleanEnv(assembleEnv)
|
|
|
|
def removeVars(self,*varsname):
|
|
"""Remove vars specified by varsname"""
|
|
res = True
|
|
assembleEnv = iniParser(self.assembleEnvFile)
|
|
for var in varsname:
|
|
res = res and assembleEnv.delVar(self.__sectionName(),var)
|
|
self._cleanEnv(assembleEnv)
|
|
return bool(res)
|
|
|
|
def _getStepCount(self,stepname):
|
|
"""Get value of variable as number"""
|
|
val = self.clVars.Get("cl_assemble_step_%s"%stepname)
|
|
if val.isdigit():
|
|
return int(val)
|
|
else:
|
|
return 0
|
|
|
|
def _appendToStep(self,stepname,newaction):
|
|
"""Append action to step"""
|
|
curval = self.clVars.Get('cl_assemble_step_%s'%stepname)
|
|
curval = filter(lambda x:x,map(lambda x:x.strip(),curval.split(',')))
|
|
if newaction in curval:
|
|
return curval
|
|
if curval:
|
|
curval.append(newaction)
|
|
else:
|
|
curval = [newaction]
|
|
return self.writeVar("cl_assemble_step_%s"%stepname,",".join(curval))
|
|
|
|
def _incStepClearMake(self,stepname):
|
|
"""Increase make step, specified by stepname, and clear make"""
|
|
self.writeVar('cl_assemble_make','')
|
|
return self.writeVar("cl_assemble_step_%s"%stepname,
|
|
str(self._getStepCount(stepname) + 1))
|
|
|
|
def make(self,logicFunc,*argv):
|
|
"""Make iso image by variables"""
|
|
self.sourceDistr = None
|
|
self.targetDistr = None
|
|
error = None
|
|
try:
|
|
try:
|
|
if not logicFunc(*argv):
|
|
return False
|
|
except KeyboardInterrupt:
|
|
raise KeyboardInterrupt
|
|
except (EOFError), e:
|
|
error = e
|
|
except (AssembleError,DistributiveError),e:
|
|
error = e
|
|
except (Exception),e:
|
|
error = ""
|
|
for i in apply(traceback.format_exception, sys.exc_info()):
|
|
error += i
|
|
except KeyboardInterrupt,e:
|
|
self.defaultPrint("\b\b")
|
|
self.printByResult(False)
|
|
self.printWARNING(_("System assemble interrupted"))
|
|
error = _("System assemble manually interrupted")
|
|
try:
|
|
if self.clTempl:
|
|
self.clTempl.closeFiles()
|
|
if error or logicFunc == self.breakFunc:
|
|
self.printByResult(False)
|
|
if self.targetDistr:
|
|
self.removeDistroInfo()
|
|
if self.targetDistr.childs:
|
|
self.printMessageForTest(
|
|
_("Releasing the partition for assemble"))
|
|
assemblePath = self.clVars.Get('cl_assemble_path')
|
|
self.targetDistr.close()
|
|
if path.exists(assemblePath):
|
|
try:
|
|
os.rmdir(assemblePath)
|
|
except OSError,e:
|
|
pass
|
|
self.printByResult(True)
|
|
if self.sourceDistr and self.sourceDistr.childs:
|
|
self.printMessageForTest(_("Releasing source data"))
|
|
self.sourceDistr.close()
|
|
self.printByResult(True)
|
|
except (AssembleError,DistributiveError),e:
|
|
if error:
|
|
error = "%s\n%s" % (str(error),_("Unmounting error"))
|
|
else:
|
|
error = _("Unmounting error")
|
|
except KeyboardInterrupt,e:
|
|
self.defaultPrint("\b\b")
|
|
error = _("Unmounting error")
|
|
try:
|
|
if error:
|
|
self.printByResult(False)
|
|
if error:
|
|
map(self.printERROR,filter(lambda x: x,str(error).split('\n')))
|
|
self.printERROR(self.msgOperationFailed)
|
|
#self.removeVars('cl_assemble_pid')
|
|
return False
|
|
if self.msgOperationComplete:
|
|
self.printSUCCESS(self.msgOperationComplete)
|
|
#self.removeVars('cl_assemble_pid')
|
|
except KeyboardInterrupt,e:
|
|
return False
|
|
return True
|
|
|
|
def revdepRebuild(self):
|
|
"""Run revdep-rebuild and check result"""
|
|
cmd = self.runChroot("revdep-rebuild -i", showProcess=True)
|
|
if not self.assemblePath:
|
|
self.assemblePath = \
|
|
self.clVars.Get('cl_assemble_path')
|
|
statusFile = path.join(self.assemblePath,
|
|
"var/cache/revdep-rebuild/6_status.rr")
|
|
if path.exists(statusFile) and \
|
|
open(statusFile,'r').read().strip() != '0':
|
|
raise AssembleError(
|
|
_("An error occurred when executing the command")+
|
|
":\n %s"%self._getCommand(cmd.command))
|
|
|
|
def checkDowngrades(self):
|
|
"""Run check downgrades"""
|
|
cmd = self.runChroot("FORMAT='{downgrade}%{FORMAT_ALL}{}' eix -I",
|
|
raiseError=False,
|
|
showProcess=True)
|
|
return True
|
|
|
|
def modulesRebuild(self):
|
|
"""Run revdep-rebuild and check result"""
|
|
if not self.assemblePath:
|
|
self.assemblePath = \
|
|
self.clVars.Get('cl_assemble_path')
|
|
modulesFile = path.join(self.assemblePath,
|
|
"var/lib/module-rebuild/moduledb")
|
|
# if file exists and not empty
|
|
if path.exists(modulesFile) and open(modulesFile,'r').read().strip():
|
|
cmd = self.runChroot("module-rebuild -X rebuild", showProcess=True)
|
|
if cmd.failed():
|
|
raise AssembleError(
|
|
_("An error occurred when executing the command")+
|
|
":\n %s"%self._getCommand(cmd.command))
|
|
|
|
def setProfile(self,newprofile,isconfigure):
|
|
"""Set profile for assembling system"""
|
|
newprofile = newprofile or ""
|
|
# if $ at end of newprofile then it be at end of profile name
|
|
if newprofile.endswith("$"):
|
|
newprofile = newprofile[:-1]
|
|
reProfile = re.compile('(^|/)%s$'%
|
|
"/([^/]+/)*".join(newprofile.strip('/').split('/')),re.S|re.I)
|
|
else:
|
|
reProfile = re.compile('(^|/)%s(/|$)'%
|
|
"/([^/]+/)*".join(newprofile.strip('/').split('/')),re.S|re.I)
|
|
allProfile = self.clVars.Get('cl_assemble_distro')
|
|
if isconfigure:
|
|
allProfile = self.clVars.Get('cl_assemble_profile')
|
|
allProfile = list(set(allProfile))
|
|
likeProfile = filter(reProfile.search,allProfile)
|
|
if likeProfile > 2:
|
|
if newprofile in likeProfile:
|
|
likeProfile = [newprofile]
|
|
if len(likeProfile) != 1:
|
|
if isconfigure:
|
|
typeProfileList = _("profile symlink targets")
|
|
else:
|
|
typeProfileList = _("distributions for assemble")
|
|
if newprofile != 'list':
|
|
if not likeProfile:
|
|
self.printERROR(_("wrong value for '--profile'"))
|
|
self.printERROR(
|
|
_("specify '-p list' to print all available %s")%
|
|
typeProfileList )
|
|
return False
|
|
else:
|
|
self.printERROR(
|
|
_("The specified value of '--profile' is ambiguous. "
|
|
"Please specify the profile with more precision."))
|
|
self.defaultPrint(_("Select profile from")+":\n")
|
|
else:
|
|
likeProfile = allProfile
|
|
if likeProfile:
|
|
self.defaultPrint(
|
|
(_("Available %s")%typeProfileList)+":\n")
|
|
elif not isconfigure:
|
|
self.printERROR(_("No distribution to assemble"))
|
|
map(self.printSUCCESS,sorted(likeProfile))
|
|
return False
|
|
else:
|
|
newprofile = likeProfile[0]
|
|
newprofile = self._shortToLongProfileName(newprofile)
|
|
self.clVars.Set('os_assemble_system_profile',newprofile,True)
|
|
return True
|
|
|
|
def getValidSource(self):
|
|
"""Get valid sources"""
|
|
distRep = DistributiveRepository(
|
|
self.clVars.Get('cl_assemble_image_path'))
|
|
return distRep._getAvailableShortnames()
|
|
|
|
def setName(self,name):
|
|
"""Set name for assembling system"""
|
|
reRight = re.compile(
|
|
r"^([%(alnum)s]+)(?:/([%(alnum)s ]+)(?:/([%(alnum)s]*))?)?$"%
|
|
{'alnum':"A-Za-z0-9"})
|
|
res = reRight.search(name)
|
|
if res:
|
|
shortname,name,subname = res.groups()
|
|
if not shortname is None:
|
|
self.clVars.Set('os_assemble_linux_shortname',shortname,True)
|
|
if not name is None:
|
|
self.clVars.Set('os_assemble_linux_name',name,True)
|
|
if not subname is None:
|
|
self.clVars.Set('os_assemble_linux_subname',subname,True)
|
|
return True
|
|
return False
|
|
|
|
def _shortToLongProfileName(self,newprofile):
|
|
"""Convert short profile name to full name"""
|
|
if newprofile.startswith("calculate"):
|
|
return path.join("../var/lib/layman/calculate/profiles",
|
|
newprofile)
|
|
else:
|
|
return path.join("../usr/portage/profiles",
|
|
newprofile)
|
|
|
|
def checkVariables(self,printVars=None):
|
|
"""Check and fix variables values"""
|
|
def printVarError(varname):
|
|
self.printERROR(_("Wrong value in '%(var)s' variable: '%(val)s'")%
|
|
{'var':varname, 'val':self.clVars.Get(varname)})
|
|
discardEmpty = lambda x : filter(lambda y:y,x)
|
|
|
|
sync = self.clVars.Get('cl_assemble_sync')
|
|
if sync and not self.setSyncMirror(sync) and not printVars:
|
|
printVarError('cl_assemble_sync')
|
|
return False
|
|
profile = self.clVars.Get('os_assemble_system_profile')
|
|
profilesFullname = map(self._shortToLongProfileName,
|
|
self.clVars.Get('cl_assemble_profile'))
|
|
profilesFullname += map(lambda x:x[2:],profilesFullname)
|
|
if profile in profilesFullname:
|
|
if profile[0] == '/':
|
|
self.clVars.Set('os_assemble_system_profile',"..%s"%profile,
|
|
True)
|
|
elif not printVars and profile:
|
|
printVarError('os_assemble_system_profile')
|
|
return False
|
|
availableDev = self.clVars.Get('cl_assemble_available_dev').split(',')
|
|
availableDev = discardEmpty(availableDev)
|
|
osDiskDev = self.clVars.Get('os_disk_dev')
|
|
if availableDev:
|
|
badDevs = filter(lambda x:not x in osDiskDev,availableDev)
|
|
if badDevs:
|
|
printVarError('cl_assemble_available_dev')
|
|
self.printERROR(_("Device '%s' does not exist")%badDevs[0])
|
|
return False
|
|
return True
|
|
|
|
def tryUseAvailable(self):
|
|
"""Check free available device and set valut to os_assemble_root_dev"""
|
|
distros = self.clVars.Get('cl_assemble_distro')
|
|
assembleEnv = iniParser(self.assembleEnvFile)
|
|
discardEmpty = lambda x : filter(lambda y:y,x)
|
|
busyDevs = \
|
|
map(lambda x:x.encode('utf-8') if type(x) == unicode else x,
|
|
discardEmpty(
|
|
map(lambda x:assembleEnv.getVar(x,'os_assemble_root_dev'),
|
|
distros)))
|
|
discardBusy = lambda x : filter(lambda y:not (y in busyDevs
|
|
or isMount(y)),x)
|
|
availableDev = self.clVars.Get('cl_assemble_available_dev').split(',')
|
|
availableDev = discardEmpty(availableDev)
|
|
freeDev = discardBusy(availableDev)
|
|
if freeDev:
|
|
rootDev = random.choice(freeDev)
|
|
self.clVars.Set('os_assemble_root_dev',rootDev,True)
|
|
self.saveVars('os_assemble_root_dev')
|
|
return True
|
|
return False
|
|
|
|
def getCurrentNvidiaBinary(self):
|
|
"""Get versions already installed nvidia drivers"""
|
|
packagePath = \
|
|
path.join(self.clVars.Get('cl_assemble_path'),
|
|
'usr/portage/packages')
|
|
x11DriversPath = path.join(packagePath,'x11-drivers')
|
|
if not path.exists(x11DriversPath):
|
|
return []
|
|
return map(lambda x:x.groups()[1],
|
|
filter(lambda x:x,
|
|
map(self.reVerSplit.search,
|
|
os.listdir(x11DriversPath))))
|
|
|
|
def fetchDrivers(self):
|
|
"""Fetch propreitary drivers"""
|
|
if self.clVars.Get('cl_assemble_withvideo_set') == "on":
|
|
drivers = [
|
|
('nvidia-drivers',
|
|
'x11-drivers/nvidia-drivers'),
|
|
('nvidia-drivers',
|
|
'\\<x11-drivers/nvidia-drivers-174'),
|
|
('nvidia-drivers',
|
|
'\\<x11-drivers/nvidia-drivers-97'),
|
|
('ati-drivers',
|
|
'x11-drivers/ati-drivers')
|
|
]
|
|
else:
|
|
drivers = []
|
|
chrootPath = self.clVars.Get('cl_assemble_path')
|
|
distDir = '/usr/portage/distfiles'
|
|
pathDistDir = pathJoin(chrootPath,distDir)
|
|
if not path.exists(pathDistDir):
|
|
os.mkdir(pathDistDir)
|
|
os.chmod(pathDistDir,02775)
|
|
os.chown(pathDistDir,0,250)
|
|
if self.startMessage:
|
|
self.startMessage = ""
|
|
self.defaultPrint("\n")
|
|
needFiles = []
|
|
infoprocess = self.runChroot(
|
|
"emerge --info",raiseError=False,joinErr=True)
|
|
curDistdir = \
|
|
map(lambda x:x.strip().rpartition('=')[-1].strip('"\''),
|
|
filter(lambda x:x.startswith("DISTDIR"),
|
|
infoprocess))
|
|
if curDistdir:
|
|
curDistdir = curDistdir[0]
|
|
else:
|
|
curDistdir = '/var/calculate/remote/distfiles'
|
|
while drivers:
|
|
repeatDrivers = []
|
|
for verName,drvVer in drivers:
|
|
rePackage = re.compile("^\[ebuild[^\]]+]\s+(\S+)")
|
|
checkprocess = self.runChroot(
|
|
"emerge -pv %s"%
|
|
drvVer, raiseError=False,joinErr=True)
|
|
# get names of dep packages
|
|
installPkgList = \
|
|
map(lambda x:x.group(1),
|
|
filter(lambda x:x,
|
|
map(rePackage.search,
|
|
checkprocess)))
|
|
# get version from emerging nvidia-driver
|
|
nvidiaVersions = \
|
|
map(lambda x:x.groups()[1],
|
|
filter(lambda x:x,
|
|
map(self.reVerSplit.search,
|
|
map(lambda x:x.groups()[0],
|
|
filter(lambda x:x,
|
|
map(rePackage.search,
|
|
filter(lambda x:verName in x,
|
|
checkprocess.readlines())))))))
|
|
|
|
if nvidiaVersions:
|
|
nvidiaVersions = nvidiaVersions[0]
|
|
else:
|
|
nvidiaVersions = "0"
|
|
self.printSUCCESS(_("When installing '%s', the following "
|
|
"packages will be installed")
|
|
%"%s-%s"%(verName,nvidiaVersions)+":")
|
|
# print dep packages (error message for probably wrong packages)
|
|
nameRight = "/%s-"%verName.partition("-")[0]
|
|
for pkg in installPkgList:
|
|
if nameRight in pkg:
|
|
self.printSUCCESS(" %s"%pkg)
|
|
else:
|
|
self.printERROR(" %s"%pkg)
|
|
if installPkgList:
|
|
self.printSUCCESS("")
|
|
self.printMessageForTest(
|
|
_("Fetching %s")%"%s-%s"%(verName,nvidiaVersions))
|
|
# run verbose package emergin for get version
|
|
fetchprocess = self.runChroot(
|
|
"emerge -f --quiet-build=n %s"%
|
|
drvVer, raiseError=False,joinErr=True)
|
|
rePackage = re.compile(
|
|
"(?:^ \* (.*?) RMD160 SHA1|File.*is already locked)")
|
|
# get fetched files
|
|
fetchedFiles = \
|
|
map(lambda x:x.groups()[0],
|
|
filter(lambda x:x,
|
|
map(rePackage.search,
|
|
fetchprocess)))
|
|
if None in fetchedFiles:
|
|
repeatDrivers.append((verName,drvVer))
|
|
self.printByResult(skip=True)
|
|
else:
|
|
self.printByResult(fetchprocess.success())
|
|
needFiles += fetchedFiles
|
|
self.defaultPrint("\n")
|
|
drivers = repeatDrivers
|
|
if drivers:
|
|
self.printMessageForTest(" " +
|
|
_("Waiting for unlock %s")%drivers[0][0])
|
|
time.sleep(10)
|
|
self.printByResult(True)
|
|
|
|
needFiles = set(needFiles)
|
|
fetchedList = set(listDirectory(pathDistDir))
|
|
removedList = fetchedList - needFiles
|
|
self.printMessageForTest(" " +
|
|
_("Cleaning %s")%distDir)
|
|
map(lambda x:os.rmdir(x) if path.isdir(x) else os.unlink(x),
|
|
filter(lambda x:path.exists(x),
|
|
map(lambda x:pathJoin(chrootPath,distDir,x),
|
|
removedList)))
|
|
map(lambda x:copyfile(x[0],x[1]),
|
|
filter(lambda x:path.exists(x[0]) and not path.exists(x[1]),
|
|
map(lambda x:(pathJoin(chrootPath,curDistdir,x),
|
|
pathJoin(chrootPath,distDir,x)),
|
|
needFiles - fetchedList)))
|
|
self.printByResult(True)
|
|
|
|
def makeNvidiaDrivers(self):
|
|
"""Emerge all nvidia-drivers as binary"""
|
|
def removeNvidiaByVer(chrootPath,pkgDir,pkgName,versList):
|
|
map(lambda x:os.unlink(x),
|
|
filter(lambda x:path.exists(x),
|
|
map(lambda x:pathJoin(chrootPath,pkgDir,
|
|
pkgName+"-%s.tbz2"%x),
|
|
versList)))
|
|
verLt = lambda x,y: cmpVersion(x,y) < 0
|
|
verGe = lambda x,y: cmpVersion(x,y) >= 0
|
|
pkgCategory = "x11-drivers"
|
|
pkgName = "%s/nvidia-drivers"%pkgCategory
|
|
chrootPath = self.clVars.Get('cl_assemble_path')
|
|
varDbPath = path.join(chrootPath,'var/db/pkg')
|
|
x11DriversPath = path.join(varDbPath,'x11-drivers')
|
|
# if system has not nvidia-drivers then nvidia will not be updated
|
|
if not path.exists(x11DriversPath) or \
|
|
not filter(lambda x:x.startswith('nvidia-drivers'),
|
|
os.listdir(x11DriversPath)):
|
|
self.printByResult(skip=True)
|
|
return True
|
|
pkgDir = '/usr/portage/packages'
|
|
pathPackages = pathJoin(chrootPath,pkgDir,"Packages")
|
|
if self.startMessage:
|
|
self.startMessage = ""
|
|
self.defaultPrint("\n")
|
|
# get version list of installed binary nvidia-drivers
|
|
allInstalled = self.getCurrentNvidiaBinary()
|
|
if self.__isPackageBuilded(re.compile('sys-kernel/.*source.*')):
|
|
removeNvidiaByVer(chrootPath,pkgDir,pkgName,allInstalled)
|
|
allInstalled = []
|
|
drivers = (('96.XX.XX','97'),
|
|
('173.XX.XX','174'))
|
|
needRegenPackages = False
|
|
for verName,drvVer in drivers:
|
|
self.printMessageForTest(" " +
|
|
_("Assembling %s")%"nvidia-drivers-%s"%verName)
|
|
# run verbose package emergin for get version
|
|
checkprocess = self.runChroot(
|
|
"emerge -vp \<%s-%s"%
|
|
(pkgName,drvVer),raiseError=False,joinErr=True)
|
|
rePackage = re.compile("^\[ebuild[^\]]+]\s+(\S+)")
|
|
# get version from emerging nvidia-driver
|
|
nvidiaVersions = \
|
|
map(lambda x:x.groups()[1],
|
|
filter(lambda x:x,
|
|
map(self.reVerSplit.search,
|
|
map(lambda x:x.groups()[0],
|
|
filter(lambda x:x,
|
|
map(rePackage.search,
|
|
checkprocess))))))
|
|
# nvidia-driver for this version absent
|
|
if not nvidiaVersions:
|
|
self.printByResult(False)
|
|
continue
|
|
|
|
nvidiaVersion = nvidiaVersions[0]
|
|
# get version for this version range
|
|
verInstall = filter(lambda x:verLt(x,drvVer), allInstalled)
|
|
# discard this
|
|
allInstalled = filter(lambda x:verGe(x,drvVer), allInstalled)
|
|
# if package not newer
|
|
if verInstall:
|
|
if filter(lambda x:verGe(x,nvidiaVersion),verInstall):
|
|
self.printByResult(skip=True)
|
|
continue
|
|
# remove old version
|
|
else:
|
|
removeNvidiaByVer(chrootPath,pkgDir,pkgName,verInstall)
|
|
|
|
# remove package if it exists
|
|
needRegenPackages = True
|
|
# build binary
|
|
process = self.runChroot("PKGDIR='%s' emerge -B \<%s-%s"%
|
|
(pkgDir,pkgName,drvVer),raiseError=False)
|
|
|
|
self.printByResult(process.success())
|
|
|
|
if needRegenPackages:
|
|
self.regenPackages(chrootPath,pkgDir)
|
|
return True
|
|
|
|
def regenPackages(self,chrootPath,pkgDirPath):
|
|
"""Regenerate packages and clean SYNC param"""
|
|
def fixKeywords(s):
|
|
if s.startswith("KEYWORDS:"):
|
|
return "KEYWORDS: amd64 x86\n"
|
|
else:
|
|
return s
|
|
pathPackages = pathJoin(chrootPath,pkgDirPath,"Packages")
|
|
# remove Packages if it recreated
|
|
if path.exists(pathPackages):
|
|
os.unlink(pathPackages)
|
|
self.runChroot("PKGDIR='%s' emaint binhost"%pkgDirPath)
|
|
if path.exists(pathPackages):
|
|
# remove SYNC param
|
|
filtredPackages = \
|
|
map(fixKeywords,
|
|
filter(lambda x:not x.startswith("SYNC:"),
|
|
open(pathPackages,'r')))
|
|
open(pathPackages,'w').writelines(filtredPackages)
|
|
|
|
def binaryCleaning(self):
|
|
"""Clean binary repository"""
|
|
chrootPath = self.clVars.Get('cl_assemble_path')
|
|
pkgDir = pathJoin(chrootPath,
|
|
self.clVars.Get('cl_assemble_pkgdir'))
|
|
dbPkg = pathJoin(chrootPath, 'var/db/pkg')
|
|
|
|
try:
|
|
if not path.exists(dbPkg):
|
|
os.makedirs(dbPkg)
|
|
if not path.exists(pkgDir):
|
|
os.makedirs(pkgDir)
|
|
if path.exists(dbPkg) and path.exists(pkgDir):
|
|
# get pkg list from distro
|
|
pkgList = \
|
|
reduce(lambda x,y:x+y,
|
|
map(lambda x:map(lambda z:path.join(x,"%s.tbz2"%z),
|
|
os.listdir(path.join(dbPkg,x))),
|
|
os.listdir(dbPkg)),[])
|
|
# get binary packages
|
|
binList = \
|
|
reduce(lambda x,y:x+y,
|
|
map(lambda x:map(lambda z:path.join(x,z)[len(pkgDir)+1:],
|
|
os.listdir(path.join(x))),
|
|
filter(lambda x:path.isdir(x),
|
|
map(lambda x:path.join(pkgDir,x),
|
|
os.listdir(pkgDir)))),[])
|
|
|
|
# remove files which in binary and not in db/pkg
|
|
map(lambda x:os.unlink(x),
|
|
map(lambda x:pathJoin(pkgDir,x),
|
|
list(set(binList)-set(pkgList))))
|
|
|
|
# remove empty directories
|
|
map(lambda x:os.rmdir(x),
|
|
filter(lambda x:path.isdir(x) and not os.listdir(x),
|
|
map(lambda x:path.join(pkgDir,x),
|
|
os.listdir(pkgDir))))
|
|
|
|
#packagesDir = 'usr/portage/packages'
|
|
#x11_drivers = 'x11-drivers'
|
|
#nvidiaDir = pathJoin(chrootPath, packagesDir,x11_drivers)
|
|
|
|
#pkgDirX11Drivers = pathJoin(pkgDir,'x11-drivers')
|
|
#if not path.exists(pkgDirX11Drivers):
|
|
# os.makedirs(pkgDirX11Drivers,mode=0755)
|
|
#map(lambda x:copyfile(pathJoin(nvidiaDir,x),
|
|
# pathJoin(pkgDirX11Drivers,x)),
|
|
# listDirectory(nvidiaDir))
|
|
|
|
self.regenPackages(chrootPath,pkgDir[len(chrootPath):])
|
|
else:
|
|
self.printByResult(skip=True)
|
|
except OSError,e:
|
|
raise AssembleError(str(e))
|
|
return True
|
|
|
|
def createMaskList(self,chrootdir,filename):
|
|
"""Create package mask list by chrootdir"""
|
|
pkgdir = path.join(chrootdir,'var/db/pkg')
|
|
reVerSplit = re.compile(r"^(.*?)-(([^-]+?)(?:-(r\d+))?)$",re.S)
|
|
if not path.exists(chrootdir):
|
|
return False
|
|
try:
|
|
packageList= sorted(reduce(lambda x,y:x+map(lambda x:path.join(y,x),
|
|
os.listdir(path.join(pkgdir,y))), os.listdir(pkgdir),[]))
|
|
open(filename,'w').writelines(
|
|
map(lambda x:"%s\n"%x,
|
|
map(lambda x:x.groups()[0],
|
|
filter(lambda x:x,
|
|
map(reVerSplit.search,
|
|
packageList)))))
|
|
except (IOError,OSError),e:
|
|
return False
|
|
return True
|
|
|
|
def createUnmaskList(self,chrootdir,filename):
|
|
"""Create package unmask list by chrootdir"""
|
|
pkgdir = path.join(chrootdir,'var/db/pkg')
|
|
#x11_bindir = path.join(chrootdir,'usr/portage/packages/x11-drivers')
|
|
if not path.exists(chrootdir):
|
|
return False
|
|
try:
|
|
packageList= sorted(reduce(lambda x,y:x+map(lambda x:path.join(y,x),
|
|
os.listdir(path.join(pkgdir,y))), os.listdir(pkgdir),[]))
|
|
#packageList = \
|
|
# sorted(packageList+
|
|
# map(lambda x:path.join('x11-drivers',x[:-5]),
|
|
# filter(lambda x:x.endswith('.tbz2'),
|
|
# listDirectory(x11_bindir))))
|
|
open(filename,'w').writelines(map(lambda x:"=%s\n"%x,packageList))
|
|
except (IOError,OSError),e:
|
|
return False
|
|
return True
|
|
|
|
def createUseList(self,chrootdir,filename):
|
|
"""Create package uselist by chrootdir"""
|
|
pkgdir = path.join(chrootdir,'var/db/pkg')
|
|
def calcUseFlags(pkg):
|
|
iusePath = path.join(pkgdir,pkg,"IUSE")
|
|
usePath = path.join(pkgdir,pkg,"USE")
|
|
if path.exists(iusePath):
|
|
IUSE = set(
|
|
map(lambda x: x[1:] if x and x[0] in ("-","+") else x,
|
|
open(iusePath,"r").read().strip().split()))
|
|
else:
|
|
return ""
|
|
if path.exists(usePath):
|
|
USE = set(open(usePath,"r").read().strip().split())
|
|
else:
|
|
USE = set([])
|
|
plus = " ".join(sorted(IUSE & USE))
|
|
minus = " ".join(sorted(map(lambda x:"-%s"%x, IUSE - USE)))
|
|
if plus:
|
|
plus = " %s"%plus
|
|
if minus:
|
|
minus = " %s"%minus
|
|
return "=%s%s%s\n"%(pkg, plus, minus)
|
|
|
|
if not path.exists(chrootdir):
|
|
return False
|
|
try:
|
|
packageList= sorted(reduce(lambda x,y:x+map(lambda x:path.join(y,x),
|
|
os.listdir(path.join(pkgdir,y))), os.listdir(pkgdir),[]))
|
|
|
|
open(filename,'w').writelines(map(calcUseFlags,packageList))
|
|
except (IOError,OSError),e:
|
|
return False
|
|
return True
|
|
|
|
def createMaskUnmaskList(self):
|
|
"""Action create mask unmask list"""
|
|
baseDir = self.clVars.Get('cl_assemble_pkgdir')
|
|
name = "package"
|
|
if not path.exists(baseDir):
|
|
os.makedirs(baseDir,mode=0755)
|
|
maskName = pathJoin(baseDir,"%s.mask"%name)
|
|
unmaskName = pathJoin(baseDir,"%s.unmask"%name)
|
|
useName = pathJoin(baseDir,"%s.use"%name)
|
|
if self.createMaskList(self.clVars.Get('cl_assemble_path'),
|
|
maskName) and \
|
|
self.createUnmaskList(self.clVars.Get('cl_assemble_path'),
|
|
unmaskName) and \
|
|
self.createUseList(self.clVars.Get('cl_assemble_path'),
|
|
useName):
|
|
return True
|
|
return False
|