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

1123 lines
43 KiB

#-*- coding: utf-8 -*-
from os.path import exists as pathexists
from os.path import dirname as pathdirname
from os.path import join as pathjoin
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
from shutil import copyfile
from cl_template import _terms
from subprocess import Popen,PIPE
from cl_fill import fillVars
import threading
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'
}
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 _get_from_metapackage(self,directory,shortname):
"""Get version from meta package"""
metaPkgs = filter(lambda x:"%s-meta"%shortname.lower() in x,
os.listdir(pathjoin(directory,
'var/db/pkg/app-misc/')))
if metaPkgs:
reFindVer = re.compile("(?<=\-)\d+\.?\d*\.?\d*")
findVer = reFindVer.search(metaPkgs[0])
if findVer:
return findVer.group()
return None
def _get_from_calculate_ini(self,directory):
"""Get version from calculate ini"""
path = pathjoin(directory,'/etc/calculate/calculate.ini')
if os.path.exists(path):
FD = open(path)
data = FD.readlines()
FD.close()
shortNameList = filter(lambda y:y,
map(lambda x:\
len(x.split("="))==2 and\
x.split("=")[0]=="linuxver" and\
x.split("=")[1].strip(), data))
if shortNameList:
return shortNameList[0]
def _getdistrshortname(self,directory='/'):
"""Get distributive shortname"""
makeprofile = pathjoin(directory,'etc/make.profile')
if os.path.exists(makeprofile):
link = os.readlink(makeprofile)
reMakeProfileLink = re.compile('calculate/(desktop|server)/(%s)'%
"|".join(fillVars.dictLinuxName.keys()),re.S)
shortnameSearch = reMakeProfileLink.search(link)
if shortnameSearch:
return shortnameSearch.groups()[1]
path = pathjoin(directory,'etc/calculate/calculate.ini')
if os.path.exists(path):
FD = open(path)
data = FD.readlines()
FD.close()
shortNameList = filter(lambda y:y,
map(lambda x:\
len(x.split("="))==2 and\
x.split("=")[0]=="calculate" and\
x.split("=")[1].strip(), data))
if shortNameList:
return shortNameList[0]
gentooFile = pathjoin(directory,"etc/gentoo-release")
shortName = "Linux"
if os.path.exists(gentooFile):
shortName = "Gentoo"
return shortName
def _getdistrinfo(self,filename):
"""Get information by distributive"""
if os.path.isdir(filename):
d = self.ini_to_dict(pathjoin(filename,
'etc/calculate/calculate.ini'))
if d and pathexists(pathjoin(filename,'lib64')):
d['march'] = 'x86_64'
else:
d['march']= 'i686'
if d:
d['ext'] = 'dir'
d["name"] = self._getdistrshortname(filename)
d['ver'] = self._get_from_metapackage(filename,d["name"]) or \
self._get_from_calculate_ini(filename) or \
"0"
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(path):
if pathexists(pathjoin(path,'etc/make.profile')):
return [path]
else:
# discard inner directories
return filter(lambda x:not os.path.isdir(pathjoin(path,x)),
os.listdir(path))
# get lists files in directories
allFiles = map(lambda x: map(lambda y: pathjoin(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 os.path.isdir(filename):
return DirectoryDistributive(filename)
else:
raise DistributiveError(_("Wrong distributive") + " '%s':\n%s"\
%(filename,ftype))
def extcomparator(self,*exts):
avexts = ("iso","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):
"""Get the actualest distributive"""
availDistrs = self._getAvailableDistributives(system,shortname,
march,version)
availDistrs = filter(lambda x:x[1],
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"
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)
if type(mes) == types.ListType:
mes = "\n".join(map(lambda x: x.strip(), mes))
return res,mes
def getDirectory(self):
return self.convertToDirectory().directory
def _makeDirectory(self,path):
"""Make directory and parent.
If directory exists then return False else True"""
try:
parent = os.path.split(os.path.normpath(path))[0]
if not pathexists(parent):
self._makeDirectory(parent)
else:
if pathexists(path):
return False
os.mkdir(path)
return True
except (Exception,KeyboardInterrupt),e:
raise DistributiveError(_("Cann't create directory") +" '%s':\n%s"
%(path,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,KeyboardInterrupt),e:
raise DistributiveError(_("Cann't copy") + " '%s' to '%s':\n%s"\
%(infile,outfile,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:
res,errmes = self.runOsCommand("rsync -a -x %s/ %s/" % \
(fromdir,todir))
except Exception:
res = False
except KeyboardInterrupt:
res = KeyboardInterrupt
spin.stop()
if res == 0:
return True
elif res == KeyboardInterrupt:
raise KeyboardInterrupt()
else:
raise DistributiveError(_("Cann't copy file from") +\
" '%s' " %fromdir + _("to") +\
" '%s':\n%s" %(todir,errmes))
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)])
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 pathexists(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):
# TODO: need node value for ext2 ext3
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':'/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 changeSystemID(self,dev,systemid):
parentDir = os.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: os.path.split(dev)[-1] in \
reduce(lambda y,z:y+z[1],
os.walk(os.path.join('/sys/block',x)),[]), device)
if parentdevices:
return parentdevices[0]
return dev[:-1]
pipe = Popen(["/sbin/fdisk",
pathjoin('/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 pathexists(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):
res,errmes = self.runOsCommand("/usr/bin/mksquashfs %s/ %s"%
(directory,file))
if res != 0:
raise DistributiveError(_("Cann't create squashfs") + " '%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.packToSquash(dFrom.directory, self.file)
class IsoDistributive(Distributive):
reLive = re.compile(r"^live[^.]*(\.(\d+))?\.squashfs$",re.S)
def __init__(self,file,parent=None,mdirectory="/mnt/cdrom",
bdirectory="/var/calculate/tmp/iso"):
Distributive.__init__(self,parent=parent)
self.file = file
self.mdirectory = mdirectory
self.bdirectory = bdirectory
def _mountIso(self,file,directory):
self._makeDirectory(directory)
self._mountToDirectory(file,directory,mountopts="-o loop")
def _umountIso(self,directory):
self._umountDirectory(directory)
self._removeDirectory(directory)
def _getLastLive(self,directory):
curfile = None
curnum = -1
for file in os.listdir(directory):
res = self.reLive.search(file)
if res:
if res.groups()[1]:
num = int(res.groups()[1])
else:
num = 0
if num > curnum:
curfile = file
curnum = num
return curfile
def convertToSquash(self):
mdirectory = self.mdirectory
for child in self.childs:
if isinstance(child,SquashDistributive) and \
mdirectory in child.file:
return child
mdirectory = self._getMntDirectory(mdirectory)
self._mountIso(self.file,mdirectory)
fileLive = self._getLastLive(mdirectory)
if not fileLive:
raise DistributiveError(_("Iso %s doesn't contain live image") %
self.file)
return SquashDistributive(pathjoin(mdirectory,fileLive),
parent=self)
def releaseChild(self,child):
"""Umount child Directory distributive"""
if isinstance(child,SquashDistributive):
self._umountIso(pathdirname(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(pathjoin(directory,"isolinux"))
self._copyfile("/usr/share/syslinux/isolinux.bin",
pathjoin(directory,"isolinux/isolinux.bin"))
def packToIso(self,directory,file):
# remove previous version of iso
try:
if pathexists(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,
pathjoin(isoDirectory,"livecd.squashfs"))
else:
distDirectory = source.convertToDirectory()
squashDistr = SquashDistributive(
pathjoin(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 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 (pathexists(pathjoin(directory,"workspace")) and \
pathexists(pathjoin(directory,"delta")) and \
pathexists(pathjoin(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 "+\
"-o udba=relval,br:%(work)s=rw:%(delta)s=ro+wh:%(static)s=ro" %\
{"work":pathjoin(source,"workspace"),
"delta":pathjoin(source,"delta"),
"static":pathjoin(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 \
kdirectory in child.directory:
return child
mdirectory = self._getMntDirectory(mdirectory)
self._mountLiveImage(self.file,pathjoin(self.directory,"calculate"))
self._mountLayers(self.file,mdirectory)
return DirectoryDistributive(mdirectory,parent=self)
def releaseChild(self,child):
"""Umount child Directory distributive"""
if isinstance(child,DirectoryDistributive):
self._umountLayers(child.directory)
self._umountLiveImage(pathjoin(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(pathjoin(directory,scrDirectory))
def installFrom(self, source):
"""Install distributive to partition from source distributive"""
# get currect partition as directory
distrTo = self.mountToDirectory()
scratchDirectory = distrTo().directory
try:
# getting squash from source
if isinstance(source,SquashDistributive):
self._copyfile(source.file,
pathjoin(scratchDirectory,"livecd.squashfs"))
else:
distDirectory = source.convertToDirectory()
squashDistr = SquashDistributive(
pathjoin(scratchDirectory,"livecd.squashfs"))
squashDistr.installFrom(distDirectory)
# prepare scratch
self.prepareScratch(directory)
except DistributiveError,e:
self._removeDirectory(scratchDirectory)
raise e
except KeyboardInterrupt,e:
self._removeDirectory(scratchDirectory)
raise DistributiveError(_("Keyboard interrupt"))