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

399 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.cl_datavars import Variables,VariableError
from calculate.lib.utils.common import getSupportArch,getTupleVersion
from calculate.lib.utils.files import readLinesFile, listDirectory
from calculate.lib.variables import Linux
from calculate.install.cl_distr import Distributive
from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_install',sys.modules[__name__])
class Distro(Variables):
vars = ["cl_image","cl_image_path","cl_image_arch_machine",
"cl_image_linux_shortname","cl_image_linux_ver",
"cl_image_linux_build","cl_image_filename"]
# system image for installation
cl_image = {}
cl_image_filename = {'mode':'w',
'type':'string',
'opt':['--iso'],
'label':_("Installation image"),
'help':_("ISO image for installation")}
# filter by architecture
cl_image_arch_machine = {'mode':'w',
'type':'choice',
'opt':['--march'],
'label':_("Preferred processor architecture"),
'help':_("select the processor architecture")}
# filter by shortname
cl_image_linux_shortname = {'mode':'w',
'type':'choice',
'opt':['--os','-s'],
'label':_("Distributive"),
'help':_("select the operation system")}
# filter by version
cl_image_linux_ver = {'mode':'w',
'type':'string',
'label':_("Version"),
'value':"",
'help':_("select the operation system by version")}
# filter by build
cl_image_linux_build = {'mode':'w',
'type':'string',
'label':_("Build"),
'value':"",
'help':_("select the operation system by build")}
# path which contains images
cl_image_path = {'type':'list'}
def get_cl_image_arch_machine(self):
return self.Get('os_arch_machine')
def choice_cl_image_arch_machine(self):
return self.marches + ["auto"]
def set_cl_image_arch_machine(self,march):
if march == "auto":
march = getSupportArch()[-1]
return march
def get_cl_image_linux_shortname(self):
return self.Get('os_linux_shortname')
def choice_cl_image_linux_shortname(self):
return Linux.dictLinuxName.keys()
def get_cl_image_path(self):
"""Get available images search path"""
# 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)
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 get_cl_image(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 get_cl_image_filename(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 human_cl_image(self):
filename = self.Get('cl_image')
if filename:
return filename.getType()
return filename
def check_cl_image_filename(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"))
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 _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 Linux.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 getBestDistributive(self,dirs,system=None,shortname=None,march=None,
version=None, build=None,discardType=[]):
"""Get the actualest distributive"""
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))
availDistrs = sorted(availDistrs,self.sortdistrfunc,reverse=True)
if availDistrs:
return availDistrs[0][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])
def choice_cl_image_arch_machine(self):
"""Get image arch"""
return ["i686","x86_64"]
def check_cl_image_linux_shortname(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))
def check_cl_image_arch_machine(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))
def check_cl_image_linux_ver(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))
def check_cl_image_linux_build(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))