You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-2.2-install/pym/cl_distr.py

1160 lines
44 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.
from os import path
from random import choice
import string
import os
import types
from time import sleep
import re
import sys
from cl_utils import runOsCommand,isMount,removeDir,typeFile,pathJoin, \
process
14 years ago
from shutil import copyfile,copytree
from cl_template import _terms
from subprocess import Popen,PIPE,STDOUT
from cl_fill import fillVars
from cl_vars_share import varsShare
import threading
from cl_lang import lang
lang().setLanguage(sys.modules[__name__])
class Spinner(threading.Thread):
stopSignal = threading.Event()
sequence= map(lambda x:x,iter("/-\\|"))
write = sys.stdout.write
selfthread = None
def setWriteFunc(self,writeFunc):
Spinner.write = writeFunc
def init(self,checkFunction=None,interval=0.1):
self.curpos = 0
self.checkFunction = checkFunction
self.interval = interval
Spinner.stopSignal.clear()
def stop(self):
Spinner.stopSignal.set()
if Spinner.selfthread:
Spinner.selfthread.join(2)
Spinner.selfthread = None
#Spinner().write('\n')
def run(self):
self.write(self.sequence[-1])
Spinner.selfthread = self
while not Spinner.stopSignal.isSet():
if self.checkFunction and self.checkFunction():
self.write("\b%s"%self.sequence[self.curpos])
self.curpos += 1
if self.curpos >= len(self.sequence):
self.curpos = 0
sleep(self.interval)
class DistributiveError(Exception):
"""Error for distributive operations"""
pass
class DistributiveRepository:
system = {
'cds':'server',
'cld':'desktop',
'cldg':'desktop',
'cldx':'desktop',
'cls':'desktop',
'css':'server'
}
varsShare = varsShare()
marches = ['i686','x86_64']
extensiton = ['iso','tar.bz2','tar.gz','tar.7z','tar.lzma']
reDistName = re.compile("""
^.*/(?P<name>%(name)s)
-(?P<ver>%(ver)s)
-(?P<march>%(march)s)
.(?P<ext>%(ext)s)$""" %
{'name':"|".join(system.keys()),
'ver':r"(\d+\.)*\d+",
'march':"|".join(marches),
'ext':"|".join(extensiton)
}, re.X)
def __init__(self,directories=[]):
self.dirs = directories
def ini_to_dict(self,filename):
"""Convert ini values to dict"""
if os.access(filename,os.R_OK):
return dict(map(lambda x: x.strip().rpartition('=')[0::2],
open(filename,'r')))
else:
return {}
def _getdistrinfo(self,filename):
"""Get information by distributive"""
varsShare = self.varsShare
# if filename is directory
if path.isdir(filename):
distr = None
# may be directory is isodir (directory which contains iso image)
extname = "isodir"
try:
distr = IsoDistributive(filename)
filename = distr.convertToDirectory().directory
except Exception,e:
extname = "dir"
d = self.ini_to_dict(path.join(filename,
'etc/calculate/calculate.ini'))
if d and path.exists(path.join(filename,'lib64')):
d['march'] = 'x86_64'
else:
d['march']= 'i686'
if d:
d['ext'] = extname
d["name"] = varsShare.getShortnameByMakeprofile(filename) or \
varsShare.getShortnameByIni(filename) or \
varsShare.detectOtherShortname(filename) or \
"Linux"
d['ver'] = \
varsShare.getVersionFromMetapackage(filename,d["name"]) or \
varsShare.getVersionFromCalculateIni(filename) or "0"
if distr:
distr.close()
return d
else:
match = self.reDistName.match(filename)
if not match:
return {}
return match.groupdict()
def _getAvailableDistributives(self,system=None,shortname=None,march=None,
version=None):
"""Get all distributives by filter"""
def distfilter(dist):
d = self._getdistrinfo(dist)
if not d:
return False
# check filter conditions
if system and self.system(d['name']) != system or \
14 years ago
not "name" in d or not "ver" in d or \
shortname and d['name'].lower() != shortname.lower() or \
march and d['march'] != march or \
version and d['ver'] != version:
return False
else:
return True
def listdistr(pathname):
if path.exists(path.join(pathname,'etc/make.profile')):
return [pathname]
elif path.exists(path.join(pathname,'livecd')):
return [pathname]
else:
# discard inner directories
return filter(lambda x:not path.isdir( path.join(pathname,x)),
os.listdir(pathname))
# get lists files in directories
allFiles = map(lambda x: map(lambda y: path.join(x,y),
listdistr(x)),
# discard not exists distrib directories
filter(lambda x: os.access(x,os.R_OK),
self.dirs))
# filter distributives
return filter(distfilter,
# join files lists to one list
reduce(lambda x,y: x + y,
allFiles, []))
def getDistributiveByFile(self,filename):
"""Get Distributive object by filename"""
# MAGIC_COMPRESS 0x000004 Check inside compressed files
tf = typeFile(magic=0x4)
ftype = tf.getMType(filename)
if "ISO 9660 CD-ROM" in ftype:
return IsoDistributive(filename)
elif "7-zip" in ftype or \
"POSIX tar archive" in ftype:
return ArchiveDistributive(filename)
elif "Squashfs filesystem" in ftype:
return SquashDistributive(filename)
elif path.isdir(filename):
if path.exists(path.join(filename,"livecd")):
return IsoDistributive(filename)
else:
return DirectoryDistributive(filename)
else:
raise DistributiveError(_("Wrong distributive") + " '%s':\n%s"\
%(filename,ftype))
def extcomparator(self,*exts):
avexts = ("iso","isodir","dir")
vals = []
for i in exts:
if i in avexts:
vals.append(avexts.index(i))
else:
vals.append(-1)
return cmp(vals[0],vals[1])
term = _terms()
def sortdistrfunc(self,x,y):
"""Func of comparing two distributive"""
ver1,ver2 = self.term._convertVers(x[1].get('ver',""),
y[1].get('ver',""))
if ver1 != ver2:
return cmp(ver1,ver2)
else:
ext1 = x[1].get('ext',"")
ext2 = y[1].get('ext',"")
return self.extcomparator(ext1,ext2)
def getBestDistributive(self,system=None,shortname=None,march=None,
version=None,discardType=[]):
"""Get the actualest distributive"""
availDistrs = self._getAvailableDistributives(system,shortname,
march,version)
availDistrs = filter(lambda x:x[1] and "ext" in x[1] and
not x[1]["ext"] in discardType,
map(lambda x:(x,self._getdistrinfo(x)),
availDistrs))
availDistrs = sorted(availDistrs,self.sortdistrfunc,reverse=True)
if availDistrs:
return availDistrs[0][0]
else:
return None
class Distributive(object):
"""Distributive object. Parent object for all distributive."""
mountError = _("Cann't mount") + " %s:\n%s"
14 years ago
reLive = re.compile(r"^live[^.]*\.squashfs(\.(\d+))?$",re.S)
def __init__(self, parent=None):
self.childs = []
# if specified parent
if parent:
# save parent type for correct resource release
self.parent = parent
# append this object as child to specified parent
parent.childs.append(self)
else:
self.parent = None
def detach(self):
"""Detach child distributive from parent.
At example: ArchiveDistributive create child DirectoryDistributive by
unpacking to temporary directory and at close method remove it. If the
removing directroy do not need, then need call detach in
DirectoryDistributive object
dist1 = ArchiveDistributive(file="/os.tar.bz2",mdirectory="/tmp/test")
dist2 = dist1.convertToDirectory()
dist2.detach()
dist1.close()
...
"""
self.parent = None
def close(self):
"""Release all child distributive and release himself.
Need call this method at end work with object for right releasing
resources.
Example:
dist1 = PartitionDistributive(partition="/dev/sda2")
dist2 = dist1.convertToDirectory()
dist1.close()
"""
# close all child
if self.childs:
for child in reversed(self.childs):
# check detach
if child.parent:
child.close()
self.childs = []
# if has parent
if self.parent:
self.parent.releaseChild(self)
self.parent = None
def releaseChild(self,child):
"""Method of release child state of distributive
At example: PartitionDistributive may be DirectoryDistributive by
mounting it to directory. But at end this directory must be
unmounted."""
pass
def convertToDirectory(self):
"""Default c raise error about impossible convert object"""
raise DistributiveError(_("Cann't convert") + " '%s' "\
%self.__class__.__name__ + _("to") +\
" '%s'" %"DirectoryDistributive")
# def __del__(self):
# """Uncomment this method for automaticaly release all distributive
# instance"""
# self.close()
def runOsCommand(self, *argv, **kwarg):
res, mes = runOsCommand(*argv,**kwarg)
mes = "\n".join(map(lambda x: x.strip(), mes))
return res,mes
def getDirectory(self):
return self.convertToDirectory().directory
def _makeDirectory(self,pathname):
"""Make directory and parent.
If directory exists then return False else True"""
try:
parent = path.split(path.normpath(pathname))[0]
if not path.exists(parent):
self._makeDirectory(parent)
else:
if path.exists(pathname):
return False
os.mkdir(pathname)
return True
except (Exception,KeyboardInterrupt),e:
raise DistributiveError(_("Cann't create directory") +" '%s':\n%s"
%(pathname,str(e)))
def _removeDirectory(self,directory):
"""Remove directory and files contained in it"""
#print "removeDirectory:",directory
try:
removeDir(directory)
except (Exception,KeyboardInterrupt),e:
raise DistributiveError(_("Unable remove directory from") +\
" '%s':\n%s" %(directory,str(e)))
def _copyfile(self,infile,outfile):
try:
copyfile(infile,outfile)
except (Exception),e:
raise DistributiveError(_("Cann't copy") + " '%s' to '%s':\n%s"\
%(infile,outfile,str(e)))
14 years ago
def _copytree(self,indir,outdir):
try:
copytree(indir,outdir,symlinks=True)
except (Exception,KeyboardInterrupt),e:
raise DistributiveError(_("Cann't copy") + " '%s' to '%s':\n%s"\
%(indir,outdir,str(e)))
def getRunCommands(self):
return map(lambda x:open('/proc/%s/cmdline'%x).read().strip(),
filter(lambda x:x.isdigit(),
os.listdir('/proc')))
def copy(self,fromdir,todir):
"""Copy files from 'fromdir' directory to 'todir' directory"""
def checkRsync():
try:
return len(filter(lambda x:"rsync\x00-a\x00-x" in x,
self.getRunCommands()))>2
except:
return False
spin = Spinner()
spin.init(checkFunction=checkRsync,interval=0.6)
spin.start()
try:
rsyncProcess = process("/usr/bin/rsync", "-a", "-x",
"%s/"%fromdir,"%s/"%todir,stderr=STDOUT)
res = rsyncProcess.success()
errmes = rsyncProcess.read()
except Exception,e:
res = False
errmes = str(e)
except KeyboardInterrupt:
spin.stop()
raise KeyboardInterrupt()
spin.stop()
if res is True:
return True
else:
raise DistributiveError(_("Cann't copy file from") +\
" '%s' " %fromdir + _("to") +\
" '%s':\n%s" %(todir,errmes))
def performFormat(self):
pass
def formatPartition(self,format=""):
pass
def rndString(self):
"""Get random string with len 8 char"""
return "".join([choice(string.ascii_letters+string.digits)
for i in xrange(0,8)])
14 years ago
def _getLastLive(self,directory):
"""Get last live squashfs image from directory"""
def getSquashNum(reMatch):
if reMatch.groups()[1] and reMatch.groups()[1].isdigit():
return int(reMatch.groups()[1])
else:
return 0
squashfiles = filter(lambda x:x,
map(self.reLive.search,
os.listdir(directory)))
if squashfiles:
return max(squashfiles, key=getSquashNum).group()
return None
14 years ago
def _mountToDirectory(self,file,directory,mountopts=""):
"""Mount squashfs to directory"""
if isMount(directory):
raise DistributiveError(_("Cann't mount to directory: %s\n")\
%directory+ _("Directory already mounted"))
res,errmes = self.runOsCommand("/bin/mount %s %s %s"%
(mountopts,file,directory))
if res == 0:
return True
else:
try:
self._removeDirectory(directory)
except:
pass
raise DistributiveError(self.mountError%(file,errmes))
def _umountDirectory(self,directory):
"""Umount directory"""
if isMount(directory):
for wait in [0,0.5,2,5]:
sleep(wait)
res,errmes = self.runOsCommand("/bin/umount %s"%directory)
if res == 0:
return True
raise DistributiveError(_("Cann't umount") + " %s:\n%s"%
(directory,errmes))
else:
return True
def _getMntDirectory(self,directory):
"""Get directory name, which will use for mounting or unpacking
If queried name is not free then to name append random string
"""
newDirectoryName = directory
while path.exists(newDirectoryName):
newDirectoryName = "%s.%s"%(directory,self.rndString())
return newDirectoryName
class DirectoryDistributive(Distributive):
def __init__(self,directory,parent=None):
Distributive.__init__(self,parent=parent)
self.directory = directory
if not parent:
self._makeDirectory(self.directory)
def convertToDirectory(self):
return self
def installFrom(self, source):
"""Install distributive to directory from source distributive"""
if isinstance(source,ArchiveDistributive):
source.unpackTo(self.directory)
else:
# get source distributive as directory distributive
dFrom = source.convertToDirectory()
# copy distributive from source to this
self.copy(dFrom.directory,self.directory)
class DataPartition:
"""Data partition"""
dev = None
mountPoint = None
fileSystem = "reiserfs"
isFormat = False
systemId = None
class MultiPartitions:
"""Data partition list"""
listPartitions = []
def addPartition(self, **argv):
"""Add partition in data partition list"""
dictDataPart = reduce(lambda x,y:\
x.update({y:getattr(DataPartition,y)}) or x,
filter(lambda x: not x.startswith('_'),
DataPartition.__dict__),{})
updateAttrData = filter(lambda x: x[1]!=None, dictDataPart.items())
defaultAttr = []
for attrName, attrValue in updateAttrData:
if not attrName in argv.keys():
defaultAttr.append(attrName)
argv[attrName] = attrValue
if set(argv.keys()) != set(dictDataPart.keys()):
notFoundAttr = set(dictDataPart.keys()) - set(argv.keys())
if notFoundAttr:
raise DistributiveError(_("Were not specified attributes (%s)")\
%", ".join(map(lambda x:"DataPartition.%s"%x, notFoundAttr)))
unnecessaryAttr = (set(dictDataPart.keys()) ^ set(argv.keys())) -\
set(dictDataPart.keys())
if unnecessaryAttr:
raise DistributiveError(_("Not used attributes (%s)")\
%", ".join(map(lambda x:"DataPartition.%s"%x, unnecessaryAttr)))
else:
partObj = DataPartition()
for attr, value in argv.items():
if attr in defaultAttr:
continue
setattr(partObj,attr,value)
self.listPartitions.append(partObj)
def getSystemId(self):
"""Get systemID for change [None,82,...]"""
return map(lambda x: x.systemId, self.listPartitions)
def getIsFormat(self):
"""Get list is format [True,...]"""
return map(lambda x: x.isFormat, self.listPartitions)
def getFileSystems(self):
"""Get list file systems ["reiserfs",...]"""
return map(lambda x: x.fileSystem, self.listPartitions)
def getPartitions(self):
"""Get list partition ["/dev/sda",...]"""
return map(lambda x: x.dev, self.listPartitions)
def getMountPoints(self):
"""Get list mount point ["/boot",...]"""
return map(lambda x: x.mountPoint, self.listPartitions)
class PartitionDistributive(Distributive):
formatUtilities = { 'ext2':'/sbin/mkfs.ext2 %s',
'ext3':'/sbin/mkfs.ext3 %s',
'ext4':'/sbin/mkfs.ext4 %s',
'jfs':'/sbin/mkfs.jfs -f %s',
'reiserfs':'/sbin/mkfs.reiserfs -f %s',
'xfs':'/sbin/mkfs.xfs -f %s',
'vfat':'/usr/sbin/mkfs.vfat -F 32 %s',
'swap':'/sbin/mkswap %s'
}
formatId = { 'ext2' : '83',
'ext3' : '83',
'ext4' : '83',
'reiserfs' : '83',
'jfs' : '83',
'xfs' : '83',
'vfat' : 'b',
'swap' : '82'
}
def __init__(self,partition,parent=None,mdirectory="/mnt/calculate",
check=False,multipartition=None,flagRemoveDir=True,
fileSystem="reiserfs", isFormat=True,systemId=None):
"""Initialize partition distributive
mdirectory - directory for mount
check - check partition name and raise DistributiveError if partition
has bad name
"""
Distributive.__init__(self,parent=parent)
self.partition = partition
self.fileSystem = fileSystem
self.mdirectory = mdirectory
self.multipartition = multipartition
self.flagRemoveDir = flagRemoveDir
self.isFormat = isFormat
self.DirectoryObject = None
self.systemId = systemId
def _mountPartition(self,partition,directory):
"""Mount partition to directory"""
self._makeDirectory(directory)
self._mountToDirectory(partition,directory)
def _umountPartition(self,directory):
"""Umount partition and remove directory"""
self._umountDirectory(directory)
if self.flagRemoveDir:
self._removeDirectory(directory)
def releaseChild(self,child):
"""Umount child Directory distributive"""
if isinstance(child,DirectoryDistributive):
self._umountPartition(child.directory)
child.directory = None
def _mountToBind(self,srcDirectory,destDirectory,mountopts="-o bind"):
"""Mount srcDirectory to destDirectory"""
res,errmes = self.runOsCommand("/bin/mount %s %s %s"%
(mountopts,srcDirectory,destDirectory))
if res == 0:
return True
else:
try:
os.rmdir(destDirectory)
except:
pass
raise DistributiveError(self.mountError%(srcDirectory,errmes))
def _mountBind(self,srcDirectory,destDirectory):
"""Mount directory to directory"""
self._makeDirectory(destDirectory)
self._makeDirectory(srcDirectory)
self._mountToBind(srcDirectory,destDirectory)
def postinstallMountBind(self):
"""Mount bind mount point and create mount dirs"""
if self.multipartition and self.DirectoryObject:
mulipartDataBind = filter(lambda x: x[2]=="bind",
self.getMultipartData())
dirObj = self.DirectoryObject
mdirectory = dirObj.directory
for srcDir, destDir, fileSystem, isFormat in mulipartDataBind:
realDestDir = pathJoin(mdirectory, destDir)
realSrcDir = pathJoin(mdirectory, srcDir)
self._mountBind(realSrcDir, realDestDir)
isFormat = False
partObj = PartitionDistributive(realSrcDir, flagRemoveDir=False,
fileSystem=fileSystem,
isFormat=isFormat,
parent=dirObj)
DirectoryDistributive(realDestDir,parent=partObj)
def getMultipartData(self):
"""Get multipartition data"""
mulipartData = zip(self.multipartition.getPartitions(),
self.multipartition.getMountPoints(),
self.multipartition.getFileSystems(),
self.multipartition.getIsFormat())
return mulipartData
def convertToDirectory(self):
"""Convert partition to directory by mounting"""
mdirectory = self.mdirectory
for child in self.childs:
if isinstance(child,DirectoryDistributive) and \
mdirectory in child.directory:
return child
mdirectory = self._getMntDirectory(mdirectory)
self._mountPartition(self.partition,mdirectory)
dirObj = DirectoryDistributive(mdirectory,parent=self)
if self.multipartition:
mulipartDataNotBind = filter(lambda x: x[2]!="bind",
self.getMultipartData())
for dev, mountPoint, fileSystem, isFormat in mulipartDataNotBind:
if fileSystem!="swap":
realMountPoint = pathJoin(mdirectory, mountPoint)
self._mountPartition(dev,realMountPoint)
partObj = PartitionDistributive(dev, flagRemoveDir=False,
fileSystem=fileSystem,
isFormat=isFormat,
parent=dirObj)
if fileSystem!="swap":
DirectoryDistributive(realMountPoint,parent=partObj)
self.DirectoryObject = dirObj
return dirObj
def formatAllPartitions(self):
"""Format all partitions"""
dataPartitions = zip(self.multipartition.getFileSystems() +\
[self.fileSystem],
self.multipartition.getPartitions() + \
[self.partition],
self.multipartition.getIsFormat() + \
[self.isFormat],
self.multipartition.getSystemId() + \
[self.systemId])
formatPartitions = map(lambda x: (x[0],x[1]),
filter(lambda x: x[2] and x[0]!="bind",
dataPartitions))
for fileSystem, dev in formatPartitions:
if fileSystem=="swap":
self.formatSwapPartition(dev)
else:
self.formatPartition(dev, format=fileSystem)
changeidPartitions = map(lambda x: (x[3],x[1]),
filter(lambda x: x[3],
dataPartitions))
for systemid, dev in changeidPartitions:
self.changeSystemID(dev,systemid)
return True
def formatPartition(self, dev,format="reiserfs"):
"""Format partition"""
14 years ago
if not format in self.formatUtilities:
raise DistributiveError(
_("Specified '%s' format inn't supported")%format)
if dev in map(lambda y: y.split(" ")[0],
filter(lambda x: x.startswith("/"),
open("/proc/swaps"))):
raise DistributiveError(\
_("Cann't format partition %s, because it is used as swap")%
dev)
if isMount(dev):
raise DistributiveError(
_("Cann't format partition %s, because it is mounted")%dev)
if not os.access(dev,os.W_OK):
raise DistributiveError(_("Cann't format partition") + " %s:\n%s"%
(dev,_("Permission denied")))
execStr = self.formatUtilities[format]%dev
res,errmes = self.runOsCommand(execStr)
if res == 0:
return True
else:
raise DistributiveError(_("Cann't format partition") + " %s:\n%s"%
(dev,errmes))
def performFormat(self):
"""Perform format for all partition of this distributive"""
if self.multipartition:
self.formatAllPartitions()
elif self.isFormat:
self.formatPartition(self.partition,format=self.fileSystem)
def changeSystemID(self,dev,systemid):
parentDir = path.split(dev)[0]
def detectDeviceForPartition(dev):
"""Detect parent device for partition by /sys/block (sysfs)"""
device = map(lambda x:filter(lambda x:x in dev,
x[1]),
os.walk('/sys/block'))
if device:
device = device[0]
parentdevices = \
filter(lambda x: path.split(dev)[-1] in \
reduce(lambda y,z:y+z[1],
os.walk(path.join('/sys/block',x)),[]), device)
if parentdevices:
return parentdevices[0]
return dev[:-1]
pipe = Popen(["/sbin/fdisk",
path.join('/dev',detectDeviceForPartition(dev))],
stdin=PIPE, stdout=PIPE,stderr=PIPE)
pipe.stdin.write("t\n%s\n%s\nw\n"%(dev[-1],systemid))
pipe.stdin.close()
pipe.wait()
def formatSwapPartition(self, dev):
"""Format swap partition"""
if dev in map(lambda y: y.split(" ")[0],
filter(lambda x: x.startswith("/"),
open("/proc/swaps"))):
raise DistributiveError(\
_("Cann't 'mkswap %s', swap partition is used in the \
current system") %dev)
if isMount(dev):
raise DistributiveError(
_("Cann't format partition %s, because it is mounted") %dev)
execStr = self.formatUtilities["swap"]%dev
res,errmes = self.runOsCommand(execStr)
if res == 0:
return True
else:
raise DistributiveError(_("Cann't execute '%s'")%execStr +\
"\n%s" %errmes)
def installFrom(self, source):
"""Install distributive to partition from source distributive"""
# get currect partition as directory
distrTo = self.convertToDirectory()
# install into directroy distributive from source
distrTo.installFrom(source)
class ArchiveDistributive(Distributive):
def __init__(self,file,parent=None,mdirectory="/var/calculate/tmp/stage"):
Distributive.__init__(self,parent=parent)
self.file = file
self.mdirectory = mdirectory
def _detectArchive(self,file):
"""Detect archive by "/usr/bin/file" command
Return bzip2,gzip,7z or None
"""
res,mes = self.runOsCommand("/usr/bin/file %s"%file)
if "bzip2 compressed data" in mes:
return "bzip2"
elif "gzip compressed data" in mes:
return "gzip"
elif "7-zip archive data" in mes:
return "7z"
else:
return None
def _unpackArchive(self,archfile,directory):
"""Unpack archive"""
# archive is exists
if not path.exists(archfile):
raise DistributiveError(_("File '%s' not found")%archfile)
# detect type archive
archiveType = self._detectArchive(archfile)
# make directory if archive was detected normally
if archiveType:
self._makeDirectory(directory)
# unpack archive
if archiveType == "7z":
res,mes = self.runOsCommand("7za x -so %s | tar xf - -C %s/"%
(archfile,directory))
elif archiveType == "bzip2":
res,mes = self.runOsCommand("tar xjf %s -C %s/"%
(archfile,directory))
elif archiveType == "gzip":
res,mes = self.runOsCommand("tar xf %s -C %s/"%
(archfile,directory))
else:
raise DistributiveError(_("Unknown archive type by '%s'")%file)
if res != 0:
raise DistributiveError(_("Error during unpacking\n%s")%mes)
def unpackTo(self,directory):
"""Unpack currect archive to directory"""
self._unpackArchive(self.file,directory)
def convertToDirectory(self):
"""Get archive as directory (unpack to directory)"""
# check may be the archive already unpacked
mdirectory = self.mdirectory
for child in self.childs:
if isinstance(child,DirectoryDistributive) and \
mdirectory in child.directory:
return child
# get temporary directory for unpacking
mdirectory = self._getMntDirectory(mdirectory)
dirdist = DirectoryDistributive(mdirectory,parent=self)
self._unpackArchive(self.file,mdirectory)
return dirdist
def releaseChild(self,child):
"""Remove child Directory distributive"""
if isinstance(child,DirectoryDistributive):
self._removeDirectory(child.directory)
child.directory = None
def packToArchive(self,directory,file):
res,errmes = self.runOsCommand("tar cf %s -C %s ."%(file,directory))
if res != 0:
raise DistributiveError(_("Cann't create archive") + " '%s':\n%s"%
(file,errmes))
def installFrom(self, source):
"""Install distributive to partition from source distributive"""
# get source distributive as directory distributive
dFrom = source.convertToDirectory()
# install into directroy distributive from source
self.packToArchive(dFrom.directory, self.file)
class SquashDistributive(Distributive):
def __init__(self,file,parent=None,mdirectory="/mnt/livecd"):
Distributive.__init__(self,parent=parent)
self.file = file
self.mdirectory = mdirectory
def _mountSquash(self,file,directory):
"""Mount squashfs to directory"""
self._makeDirectory(directory)
self._mountToDirectory(file,directory,mountopts="-o loop -t squashfs")
def _umountSquash(self,directory):
self._umountDirectory(directory)
self._removeDirectory(directory)
def convertToDirectory(self):
mdirectory = self.mdirectory
for child in self.childs:
if isinstance(child,DirectoryDistributive) and \
mdirectory in child.directory:
return child
mdirectory = self._getMntDirectory(mdirectory)
self._mountSquash(self.file,mdirectory)
return DirectoryDistributive(mdirectory,parent=self)
def releaseChild(self,child):
"""Umount child Directory distributive"""
if isinstance(child,DirectoryDistributive):
self._umountSquash(child.directory)
child.directory = None
def packToSquash(self,directory,file):
processMkSquash = process("/usr/bin/mksquashfs",
"%s/"%directory,file,stderr=STDOUT)
if processMkSquash.failed():
raise DistributiveError(_("Cann't create squashfs") + " '%s':\n%s"%
(file,processMkSquash.read()))
def installFrom(self, source):
"""Install distributive to partition from source distributive"""
# get source distributive as directory distributive
dFrom = source.convertToDirectory()
# install into directroy distributive from source
self.packToSquash(dFrom.directory, self.file)
class IsoDistributive(Distributive):
def __init__(self,file,parent=None,mdirectory="/mnt/cdrom",
bdirectory="/var/calculate/tmp/iso"):
Distributive.__init__(self,parent=parent)
self.file = file
if path.isdir(self.file):
self.mdirectory = self.file
else:
self.mdirectory = mdirectory
self.bdirectory = bdirectory
def _mountIso(self,file,directory):
if self.file != self.mdirectory:
self._makeDirectory(directory)
self._mountToDirectory(file,directory,mountopts="-o loop")
def _umountIso(self,directory):
if self.file != self.mdirectory:
self._umountDirectory(directory)
self._removeDirectory(directory)
def convertToSquash(self):
mdirectory = self.mdirectory
for child in self.childs:
if isinstance(child,SquashDistributive) and \
mdirectory in child.file:
return child
if self.mdirectory != self.file:
mdirectory = self._getMntDirectory(mdirectory)
self._mountIso(self.file,mdirectory)
fileLive = self._getLastLive(mdirectory)
if not fileLive:
self._umountIso(mdirectory)
raise DistributiveError(_("Iso %s doesn't contain live image") %
self.file)
return SquashDistributive(path.join(mdirectory,fileLive),
parent=self)
def getIsoContentDirectory(self):
"""Return directory with content of iso image"""
squash = self.convertToSquash()
return path.dirname(squash.file)
def releaseChild(self,child):
"""Umount child Directory distributive"""
if isinstance(child,SquashDistributive):
self._umountIso(path.dirname(child.file))
child.directory = None
def convertToDirectory(self):
return self.convertToSquash().convertToDirectory()
def prepareIso(self,directory):
print(_("apply iso templates to %s/")%directory)
self._makeDirectory(path.join(directory,"isolinux"))
self._copyfile("/usr/share/syslinux/isolinux.bin",
path.join(directory,"isolinux/isolinux.bin"))
def packToIso(self,directory,file):
# remove previous version of iso
try:
if path.exists(file):
os.unlink(file)
except (Exception,KeyboardInterrupt),e:
raise DistributiveError(_("Cann't remove") +\
" %s:\n%s"%(file,str(e)))
res,errmes = self.runOsCommand(
"%(progname)s %(params)s -o %(target)s %(source)s/"%
{'progname':'/usr/bin/mkisofs',
'params':" ".join(["-b isolinux/isolinux.bin","-no-emul-boot",
"-boot-load-size 4","-boot-info-table","-iso-level 4",
"-hide boot.catalog"]),
'target':file,
'source':directory})
if res == 0:
return True
else:
raise DistributiveError(_("Cann't create iso image") + " %s:\n%s"%
(file,errmes))
def installFrom(self, source):
"""Install distributive to partition from source distributive"""
# make temporary directory for creating iso image
isoDirectory = self.bdirectory
isoDirectory = self._getMntDirectory(isoDirectory)
self._makeDirectory(isoDirectory)
try:
# getting squash from source
if isinstance(source,SquashDistributive):
self._copyfile(source.file,
path.join(isoDirectory,"livecd.squashfs"))
else:
distDirectory = source.convertToDirectory()
squashDistr = SquashDistributive(
path.join(isoDirectory,"livecd.squashfs"))
squashDistr.installFrom(distDirectory)
# prepare iso
self.prepareIso(directory)
# pack iso
self.packToIso(isoDirectory, self.file)
# remove temporary directory after creating iso image
self._removeDirectory(isoDirectory)
except DistributiveError,e:
self._removeDirectory(isoDirectory)
raise e
except KeyboardInterrupt,e:
self._removeDirectory(isoDirectory)
raise DistributiveError(_("Keyboard interrupt"))
class FlashDistributive(PartitionDistributive):
def installFrom(self, source):
"""Install distributive to partition from source distributive"""
# make temporary directory for creating iso image
distrTo = self.convertToDirectory()
# getting squash from source
if isinstance(source,IsoDistributive):
self.copy(source.getIsoContentDirectory(),distrTo.directory)
else:
raise DistributiveError(
_("Installation to flash not support %s"%
source.__class__.__name__))
class ScratchDistributive(Distributive):
def __init__(self,directory,parent=None,mdirectory="/mnt/install",
check=False):
Distributive.__init__(self,parent=parent)
self.directory = directory
self.mdirectory = mdirectory
if check and not (path.exists(path.join(directory,"workspace")) and \
path.exists(path.join(directory,"delta")) and \
path.exists(path.join(directory,"calculate"))):
raise DistributiveError(
"Wrong scratch distributive in '%s'"%directory)
def _mountLayers(self,source,target):
"""Mount squashfs to directory"""
self._makeDirectory(target)
self._mountToDirectory("none",target,
mountopts="-t aufs "+\
14 years ago
"-o udba=reval,br:%(work)s=rw:%(delta)s=ro+wh:%(static)s=ro" %\
{"work":path.join(source,"workspace"),
"delta":path.join(source,"delta"),
"static":path.join(source,"calculate")})
def _umountLayers(self,directory):
self._umountDirectory(directory)
self._removeDirectory(directory)
def _mountLiveImage(self,file,directory):
"""Mount squashfs to directory"""
self._makeDirectory(directory)
self._mountToDirectory(file,directory,mountopts="-o loop -t squashfs")
def _umountLiveImage(self,directory):
self._umountDirectory(directory)
def convertToDirectory(self):
"""Convert scrach directories to one directory"""
mdirectory = self.mdirectory
for child in self.childs:
if isinstance(child,DirectoryDistributive) and \
14 years ago
mdirectory in child.directory:
return child
mdirectory = self._getMntDirectory(mdirectory)
14 years ago
liveFile = self._getLastLive(self.directory)
self._mountLiveImage(path.join(self.directory,liveFile),
path.join(self.directory,"calculate"))
14 years ago
self._mountLayers(self.directory,mdirectory)
return DirectoryDistributive(mdirectory,parent=self)
def releaseChild(self,child):
"""Umount child Directory distributive"""
if isinstance(child,DirectoryDistributive):
self._umountLayers(child.directory)
self._umountLiveImage(path.join(self.directory,"calculate"))
child.directory = None
def installFrom(self, source):
"""Install distributive to partition from source distributive"""
# get source distributive as directory distributive
dFrom = source.convertToDirectory()
# install into directroy distributive from source
self.packToSquash(dFrom.directory, self.file)
class ScratchPartitionDistributive(PartitionDistributive):
def releaseChild(self,child):
"""Umount child Directory distributive"""
if isinstance(child,ScratchDistributive):
self._umountPartition(child.directory)
child.directory = None
def convertToDirectory(self):
"""Convert scratch partition to directory by scratch directory"""
return self.convertToScratch().convertToDirectory()
def convertToScratch(self):
mdirectory = self.mdirectory
for child in self.childs:
if isinstance(child,ScratchDistributive) and \
mdirectory in child.directory:
return child
mdirectory = self._getMntDirectory(mdirectory)
self._mountPartition(self.partition,mdirectory)
return ScratchDistributive(mdirectory,parent=self)
def prepareScratch(self,directory):
for scrDirectory in ("calculate","delta","workspace"):
self._makeDirectory(path.join(directory,scrDirectory))
14 years ago
def postinstallMountBind(self):
dirDistr = self.convertToDirectory().directory
scrDir = self.convertToScratch().directory
self._copytree(path.join(dirDistr,"boot"),
path.join(scrDir,"boot"))
14 years ago
def installFrom(self, source):
"""Install distributive to partition from source distributive"""
# get currect partition as directory
14 years ago
distrTo = self.convertToScratch()
scratchDirectory = distrTo.directory
try:
# getting squash from source
14 years ago
if isinstance(source,IsoDistributive):
source = source.convertToSquash()
if isinstance(source,SquashDistributive):
self._copyfile(source.file,
path.join(scratchDirectory,"livecd.squashfs"))
else:
distDirectory = source.convertToDirectory()
squashDistr = SquashDistributive(
path.join(scratchDirectory,"livecd.squashfs"))
squashDistr.installFrom(distDirectory)
# prepare scratch
14 years ago
self.prepareScratch(scratchDirectory)
except DistributiveError,e:
raise e
except KeyboardInterrupt,e:
raise DistributiveError(_("Keyboard interrupt"))