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-3-install/install/variables/distr.py

441 lines
16 KiB

#-*- coding: utf-8 -*-
# Copyright 2008-2012 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.
import os
import sys
from os import path
import re
import operator
from calculate.lib.datavars import Variable,VariableError,ReadonlyVariable
from calculate.lib.utils.common import getSupportArch,getTupleVersion
from calculate.lib.utils.files import readLinesFile, listDirectory
from calculate.lib.variables.linux import Linux
from calculate.install.cl_distr import Distributive
from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_install',sys.modules[__name__])
class DistroRepository(Linux):
contentCache = {}
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':"[a-z0-9]+",
'ver':r"(\d+\.)*\d+",
'march':"|".join(marches),
'ext':"|".join(extensiton)
}, re.X)
def _getDistrInfo(self,filename):
"""Get information by distributive"""
# if filename is directory
if not path.isfile(filename):
return Distributive().getInfo(filename)
else:
match = self.reDistName.match(filename)
if not match:
return {}
distdic = match.groupdict()
distdic["build"] = ""
if "ver" in distdic:
if re.match("^\d{8}$", distdic["ver"]):
distdic["build"] = distdic["ver"]
distdic["ver"] = ""
return distdic
def getImage(self,scratch,rootType,imagePath,march=None,
shortName=None,linuxVer=None,linuxBuild=None):
"""Get image by parameters"""
# exclude directory distributive for flash and scratch install
if scratch == "on" or rootType == "flash":
discardType = ["dir"]
else:
discardType = []
return self.getBestDistributive(imagePath,
march=march,
shortname=shortName,
discardType=discardType,
version=linuxVer,
build=linuxBuild)
def _getAvailableShortnames(self,dirs):
"""Get available distributives shortnames"""
distros = filter(lambda x:x,
map(self.reDistName.search,self._getAvailableDistributives(dirs)))
return sorted(list(set(map(lambda x:x.groupdict()['name'],distros))))
def opcompareByString(self,buf):
if buf:
reOp = re.compile("^(!=|=|==|<=|>=|>|<)?(\d+.*)$")
res = reOp.search(buf)
if res:
return ({'!=':operator.ne,
'=':operator.eq,
'==':operator.eq,
'>=':operator.ge,
'<=':operator.le,
'<':operator.lt,
'>':operator.gt}.get(res.group(1),operator.eq),
res.group(2))
else:
return operator.eq,buf
return None,None
def _getAvailableDistributives(self,dirs,system=None,shortname=None,march=None,
version=None,build=None):
"""Get all distributives by filter"""
def systemByName(name):
return self.dictNameSystem.get(name.upper(),"")
verCmp, version = self.opcompareByString(version)
if version:
version = getTupleVersion(version)
buildCmp, build = self.opcompareByString(build)
if build and build.isdigit():
build = int(build)
def distfilter(dist):
d = self._getDistrInfo(dist)
if not d:
return False
# check filter conditions
if system and systemByName(d['name']) != system:
return False
if not "name" in d or not "ver" in d:
return False
if shortname and d['name'].lower() != shortname.lower():
return False
if march and d['march'] != march:
return False
if version and not verCmp(getTupleVersion(d['ver']), version):
return False
if build and "build" in d and (not d['build'].isdigit() or
not buildCmp(int(d['build']),build)):
return False
return True
def listdistr(pathname):
if path.exists(path.join(pathname,'etc/make.profile')) or \
path.exists(path.join(pathname,'livecd')) or \
pathname.startswith('/dev/'):
return [pathname]
else:
# discard inner directories
return filter(lambda x:not path.isdir( path.join(pathname,x)),
listDirectory(pathname))
# get lists files in directories
allFiles = map(lambda x: map(lambda y: path.join(x,y),
listdistr(x)),
dirs)
# filter distributives
return filter(distfilter,
# join files lists to one list
reduce(lambda x,y: x + y,
allFiles, []))
def extcomparator(self,*exts):
"""Compare extensions"""
mapExts = {'iso':0,
'flash':-1,
'isodir':-2,
'partdir':-3,
'dir':-4}
return cmp(mapExts.get(exts[0],-4),mapExts.get(exts[1],-4))
def sortdistrfunc(self,x,y):
"""Func of comparing two distributive"""
ver1, ver2 = x[1].get('ver',""), y[1].get('ver',"")
if ver1 and ver2 and ver1 != "0" and ver2 != "0" and ver1 != ver2:
return cmpVersion(ver1,ver2)
build1 = getTupleVersion(x[1].get('build',""))
build2 = getTupleVersion(y[1].get('build',""))
if build1 != build2:
return cmp(build1,build2)
else:
ext1 = x[1].get('ext',"")
ext2 = y[1].get('ext',"")
return self.extcomparator(ext1,ext2)
def getAvailableDristibutives(self,dirs,system=None,shortname=None,
march=None, version=None, build=None,discardType=[]):
"""Get list available distributives"""
if shortname:
shortname = shortname.lower()
availDistrs = self._getAvailableDistributives(dirs,system,shortname,
march,version,
build)
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))
return map(lambda x:x[0],
sorted(availDistrs,self.sortdistrfunc,reverse=True))
def getBestDistributive(self,dirs,system=None,shortname=None,march=None,
version=None, build=None,discardType=[]):
"""Get the actualest distributive"""
availDistrs = self.getAvailableDristibutives(dirs,system,shortname,
march,version,build,discardType)
if availDistrs:
return availDistrs[0]
else:
return None
def _findLatestFile(self,dirs,reMatch,keyfunc):
"""Find latest file in dirs, which match by reMatch,
comparable part get by keyfunc"""
existsdirs = filter(path.exists,dirs)
listimgs = reduce(lambda x,y:x + \
map(lambda x:reMatch.search(path.join(y,x)),
listDirectory(y)),
existsdirs,[])
listimgs = filter(lambda x:x, listimgs)
if listimgs:
return max(listimgs,key=keyfunc).group()
return ""
def getBestStage(self,dirs,march=None,hardened=None):
"""Get latest stage by march"""
if march:
march = {'x86_64':'amd64'}.get(march,march)
else:
march = "[^-]+"
if hardened is None:
hardened = "(?:-hardened)?"
elif hardened == True:
hardened = "-hardened"
elif hardened == False:
hardened = ""
reStage = re.compile(r'^.*/stage3-%s%s-(\d+)\.tar\.bz2$'%
(march,hardened),re.S)
return self._findLatestFile(dirs,reStage,lambda x:x.groups()[0])
class VariableClImage(ReadonlyVariable):
"""
System image for installation
"""
def get(self):
"""Get image file from distributive repository"""
if self.Get('cl_action') != 'system':
return Distributive.fromFile('/')
filename = self.Get('cl_image_filename')
if filename:
filename = Distributive.fromFile(filename)
return filename
def humanReadable(self):
filename = self.Get('cl_image')
if filename:
return filename.getType()
return filename
class VariableClImageFilename(Variable,DistroRepository):
"""
Distributive image filename
"""
type = 'choiceedit'
opt = ['--iso']
label = _("Installation image")
help = _("ISO image for installation")
def get(self):
if self.Get('cl_action') != 'system':
return ""
return self.getImage(self.Get('os_install_scratch'),
self.Get('os_install_root_type'),
self.Get('cl_image_path'),
self.Get('cl_image_arch_machine'),
self.Get('cl_image_linux_shortname'),
self.Get('cl_image_linux_ver'),
self.Get('cl_image_linux_build'))
def check(self,isoimage):
"""Set image file"""
imageData = Distributive().getInfo(isoimage)
if not("name" in imageData and imageData.get('build','') and \
"march" in imageData):
raise VariableError(_("Wrong image file"))
def humanImageName(self,distroinfo,filepath):
distroinfo['name'] = distroinfo['name'].upper()
return "{name} {march} {build} ({filepath})".format(
filepath=filepath,**distroinfo)
def choice(self):
scratch = self.Get('os_install_scratch')
rootType = self.Get('os_install_root_type')
imagePath = self.Get('cl_image_path')
march = self.Get('cl_image_arch_machine')
shortName = self.Get('cl_image_linux_shortname')
linuxVer = self.Get('cl_image_linux_ver')
linuxBuild = self.Get('cl_image_linux_build')
if scratch == "on" or rootType == "flash":
discardType = ["dir"]
else:
discardType = []
distros = self.getAvailableDristibutives(imagePath,
march=march,
shortname=shortName,
discardType=discardType,
version=linuxVer,
build=linuxBuild)
return map(lambda x:(x,self.humanImageName(self._getDistrInfo(x),x)),
distros)
class VariableClImageArchMachine(Variable):
"""
Filter by architecture
"""
type = 'choice'
opt = ['--march']
label = _("Preferred processor architecture")
help = _("select the processor architecture")
available_arch = ["i686","x86_64"]
def get(self):
return self.Get('os_arch_machine')
def set(self,march):
if march == "auto":
march = getSupportArch()[-1]
return march
def choice(self):
return self.available_arch + ["auto"]
def check(self,value):
if self.Get('cl_action') == 'system':
if not self.Get('cl_image'):
if not self.getImage(self.Get('os_install_scratch'),
self.Get('os_install_root_type'),
self.Get('cl_image_path'),
march=value,
shortName=self.Get('cl_image_linux_shortname')):
raise VariableError(
_('Installation image of {distro} with '
"architecture '{arch}' not found").format(
distro=self.Get('cl_image_linux_shortname'),
arch=value))
class VariableClImageLinuxShortname(Variable,Linux):
"""
Filter by shortname
"""
type = 'choice'
opt = ['--os','-s']
label = _("Distributive")
help = _("select the operation system")
def get(self):
return self.Get('os_linux_shortname')
def choice(self):
return self.dictLinuxName.keys()
def check(self,value):
if self.Get('cl_action') == 'system':
if not self.Get('cl_image'):
if not self.getImage(self.Get('os_install_scratch'),
self.Get('os_install_root_type'),
self.Get('cl_image_path'),
shortName=value):
raise VariableError(
_('Installation image of {0} not found').format(value))
class VariableClImageLinuxVer(Variable):
"""
Filter by version
"""
label = _("Version")
value = ""
help = _("select the operation system by version")
def check(self,value):
if self.Get('cl_action') == 'system':
if value and not self.Get('cl_image'):
if not self.getImage(self.Get('os_install_scratch'),
self.Get('os_install_root_type'),
self.Get('cl_image_path'),
march=self.Get('cl_image_arch_machine'),
shortName=self.Get('cl_image_linux_shortname'),
linuxVer=value):
raise VariableError(
_('Installation image of {distro} with '
"version '{ver}' not found").format(
distro="%s-%s"%
(self.Get('cl_image_linux_shortname'),
self.Get('cl_image_arch_machine')),
ver=value))
class VariableClImageLinuxBuild(Variable):
"""
Filter by build
"""
label = _("Build")
value = ""
help = _("select the operation system by build")
def check(self,value):
if self.Get('cl_action') == 'system':
if value and not self.Get('cl_image'):
raise VariableError(
_('Installation image with build {build} not found').format(
build=value))
class VariableClImagePath(ReadonlyVariable):
"""
Image search path
"""
type = "list"
def get(self):
# if current distributive is live
if self.Get('os_root_type') == "livecd":
# if builder from flash then this source path '/mnt/flash'
# may be this path will be '/mnt/builder' for install
# modified system
if self.Get('os_scratch') == "on" and path.exists('/mnt/flash'):
livedistr = ['/mnt/flash']
# if system boot with kernel param 'docache'
elif path.exists('/mnt/squash'):
livedistr = ['/mnt/livecd']
# standard livecd
else:
livedistr = ['/mnt/cdrom']
else:
livedistr = []
# search all partition for source installation distributive
rootDev = self.Get('os_install_root_dev')
livedistr += \
map(lambda x:x[0],
filter(lambda x:" live" in x[1] and x[0] != rootDev,
zip(self.Get('os_disk_dev'),
self.Get('os_disk_content'))))
# add to standard path
return filter(path.exists,
['/var/calculate/remote/linux',
'/var/calculate/linux'] + livedistr)