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.
439 lines
13 KiB
439 lines
13 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
|
|
import re
|
|
from os import path
|
|
from time import sleep
|
|
from calculate.lib.datavars import Variable,VariableError,ReadonlyVariable
|
|
from calculate.lib.utils.device import (getUdevDeviceInfo,getDeviceType,
|
|
getPartitionType,getPartitionDevice,getRaidPartitions,
|
|
getLvmPartitions,getPartitionSize,getUUIDDict,
|
|
humanreadableSize)
|
|
from calculate.lib.utils.files import (listDirectory,pathJoin,readFile,FStab,
|
|
readLinesFile,process,getProgPath)
|
|
from calculate.install.cl_distr import PartitionDistributive
|
|
from calculate.install.fs_manager import FileSystemManager
|
|
|
|
|
|
from calculate.lib.cl_lang import setLocalTranslate
|
|
setLocalTranslate('cl_install',sys.modules[__name__])
|
|
|
|
class AutopartitionError(Exception):
|
|
"""
|
|
Autopartition error
|
|
"""
|
|
pass
|
|
|
|
class AutoPartition:
|
|
"""
|
|
Autopartition maker
|
|
"""
|
|
schemes = [("",
|
|
_("Manual partition")),
|
|
("{rootsize}:/;{rootsize}:;{allsize}:/var/calculate;"
|
|
"/var/calculate:/home",
|
|
_("Whole disk for double root, data, /home from data")),
|
|
("{memory}:swap;{rootsize}:/;"
|
|
"{rootsize}:;{allsize}:/var/calculate",
|
|
_("Whole disk for swap,double root and data")),
|
|
("{memory}:swap;{allsize}:/",
|
|
_("Whole disk for swap and root"))]
|
|
|
|
def recreatePartitionTable(self,device,scheme,table="dos"):
|
|
"""
|
|
"""
|
|
|
|
def recreatePartitionTableDos(self,device,scheme,memory,rootsize):
|
|
"""
|
|
"""
|
|
NEW_PARTITION_TABLE = "o\n"
|
|
NEW_PRIMARY_PARTITION = "n\np\n\n\n"
|
|
NEW_EXTENDED_PARTITION = "n\ne\n\n"
|
|
NEW_LOGICAL_PARTITION = "n\n\n"
|
|
MAX_SIZE = "\n"
|
|
WRITE_AND_QUIT = "w\nq\n"
|
|
|
|
fdiskProg = getProgPath('/sbin/fdisk')
|
|
fdisk = process(fdiskProg,device)
|
|
fdisk.write(NEW_PARTITION_TABLE)
|
|
scheme = scheme.format(memory=memory,
|
|
rootsize=rootsize,
|
|
allsize="allsize")
|
|
num = 1
|
|
for entry in scheme.split(';'):
|
|
size,mount = entry.split(':')
|
|
if size.startswith('/'):
|
|
continue
|
|
if num == 4:
|
|
fdisk.write(NEW_EXTENDED_PARTITION+MAX_SIZE)
|
|
num += 1
|
|
size = MAX_SIZE if size == "allsize" else "+%sK\n"%size
|
|
if num < 4:
|
|
fdisk.write(NEW_PRIMARY_PARTITION+size)
|
|
else:
|
|
fdisk.write(NEW_LOGICAL_PARTITION+size)
|
|
num +=1
|
|
fdisk.write(WRITE_AND_QUIT)
|
|
|
|
fdisk.success()
|
|
for waittime in (0.1,0.2,0.5,1,2,4):
|
|
if path.exists(device+str(num-1)):
|
|
return True
|
|
else:
|
|
sleep(waittime)
|
|
raise AutoPartitionError(
|
|
_("Failed to found partition %s after creating partition table")
|
|
%dev)
|
|
|
|
class VariableHrMemorySize(ReadonlyVariable):
|
|
"""
|
|
Memory size in bytes
|
|
"""
|
|
type = "int"
|
|
|
|
def get(self):
|
|
reMemTotal = re.compile(r'^MemTotal:\s*(\d+)\s*kB$')
|
|
totalMemList = filter(lambda x:x,
|
|
map(reMemTotal.search,
|
|
readLinesFile('/proc/meminfo')))
|
|
if totalMemList:
|
|
size = int(totalMemList[0].group(1))*1024
|
|
if size < 1024*1024*1024:
|
|
size = 1024*1024*1024
|
|
return str(size)
|
|
return "0"
|
|
|
|
def humanReadable(self):
|
|
return map(humanreadableSize,self.Get())
|
|
|
|
class VariableClAutopartitionDevice(Variable):
|
|
"""
|
|
Device for autopartition
|
|
"""
|
|
type = "choice"
|
|
value = ""
|
|
opt = ["-D"]
|
|
metavalue = "DEVICE"
|
|
|
|
def init(self):
|
|
self.help = _("set autopartition device")
|
|
self.label = _("Install device")
|
|
|
|
def choice(self):
|
|
return [""]+self.Get('os_device_dev')
|
|
|
|
def check(self,value):
|
|
if self.Get('cl_autopartition_scheme'):
|
|
if not value:
|
|
raise VariableError(_("For autopartition need select install"
|
|
" device"))
|
|
useDisks = self.Select('os_disk_parent',
|
|
where='os_disk_mount',
|
|
eq=value)
|
|
if value in useDisks:
|
|
raise VariableError(
|
|
_("Device already is used by current system"))
|
|
|
|
class VariableClAutopartitionScheme(Variable,AutoPartition):
|
|
"""
|
|
Autopartition scheme
|
|
"""
|
|
type = "choice"
|
|
value = ""
|
|
element = "radio"
|
|
opt = ["--autopart"]
|
|
metavalue = "AUTOPARTMODE"
|
|
|
|
def init(self):
|
|
self.help = _("autopartition scheme")
|
|
self.label = _("Install scheme")
|
|
|
|
def choice(self):
|
|
return self.schemes
|
|
|
|
class VariableClAutopartitionRootSize(Variable):
|
|
"""
|
|
Root partition size for autopartition
|
|
"""
|
|
type = "int"
|
|
opt = ["--root-size"]
|
|
metavalue = "SIZE"
|
|
|
|
def init(self):
|
|
self.label = _("Root partition size")
|
|
self.help = _("set root partition size for autopartition")
|
|
|
|
def get(self):
|
|
if self.Get('os_install_linux_system') == 'server':
|
|
return str(1024*20)
|
|
else:
|
|
return str(1024*10)
|
|
|
|
def set(self,value):
|
|
sizeMap = {'kB':1/1000.0,
|
|
'K':1/1024.0,
|
|
'M':1.0,
|
|
'Mb':1000/1024.0,
|
|
'G':1024,
|
|
'Gb':1000,
|
|
'T':1024*1024,
|
|
'Tb':1000*1000}
|
|
value = value.strip()
|
|
reSizeValue = re.compile('^(\d+)\s*(%s)?'%"|".join(sizeMap.keys()))
|
|
res = reSizeValue.search(value)
|
|
intValue = int(res.group(1))
|
|
if res.group(2):
|
|
intValue = intValue / sizeMap[res.group(2)]
|
|
return str(intValue)
|
|
|
|
def check(self,value):
|
|
if self.Get('cl_autopartition_device') and \
|
|
self.Get('cl_autopartition_scheme') and \
|
|
self.Get('cl_autopartition_free_size') <= 0:
|
|
raise VariableError(_("Selected size is too large"))
|
|
|
|
class VariableClAutopartitionTable(Variable):
|
|
"""
|
|
Partition table for autopartition
|
|
"""
|
|
type = "choice"
|
|
value = "dos"
|
|
opt = ["--partition-table"]
|
|
metavalue = "TABLE"
|
|
|
|
def init(self):
|
|
self.label = _("Partition table")
|
|
self.help = _("set partition table for autopartition")
|
|
|
|
def choice(self):
|
|
return ["dos","gpt"]
|
|
|
|
class VariableClAutopartitionDiskData(ReadonlyVariable):
|
|
"""
|
|
New partition data for autopart device
|
|
"""
|
|
type = "table"
|
|
source = ['cl_autopartition_disk_dev',
|
|
'cl_autopartition_disk_mount',
|
|
'cl_autopartition_disk_format',
|
|
'cl_autopartition_disk_size',
|
|
'cl_autopartition_disk_part']
|
|
|
|
class VariableClAutopartitionDiskDev(ReadonlyVariable):
|
|
"""
|
|
Autopartition virtual disk on device
|
|
"""
|
|
type = "list"
|
|
|
|
def generateDisks(self,dos,device,scheme,number=0):
|
|
"""
|
|
Generate disks for automount scheme
|
|
"""
|
|
number = 1
|
|
for line in scheme.split(';'):
|
|
if dos and number == 4:
|
|
number += 1
|
|
sizeOrBind, mp = line.split(':')
|
|
if not sizeOrBind.startswith('/'):
|
|
yield "%s%d"%(device,number)
|
|
number += 1
|
|
|
|
def get(self):
|
|
scheme = self.Get('cl_autopartition_scheme')
|
|
device = self.Get('cl_autopartition_device')
|
|
if scheme and device:
|
|
res = list(self.generateDisks(
|
|
self.Get('cl_autopartition_table')=='dos',
|
|
device,scheme))
|
|
return res
|
|
return []
|
|
|
|
class VariableClAutopartitionDiskMount(ReadonlyVariable):
|
|
"""
|
|
Autopartition mount points
|
|
"""
|
|
type = "list"
|
|
|
|
def generateMounts(self,scheme):
|
|
"""
|
|
Generate mount points for automount scheme
|
|
"""
|
|
for line in scheme.split(';'):
|
|
if not line.startswith('/'):
|
|
source, mp = line.split(':')
|
|
yield mp
|
|
|
|
def get(self):
|
|
scheme = self.Get('cl_autopartition_scheme')
|
|
device = self.Get('cl_autopartition_device')
|
|
if scheme and device:
|
|
return list(self.generateMounts(scheme))
|
|
return []
|
|
|
|
class VariableClAutopartitionDiskFormat(ReadonlyVariable):
|
|
"""
|
|
Autopartition disk file system
|
|
"""
|
|
type = "list"
|
|
|
|
def generateFormat(self,scheme):
|
|
"""
|
|
Generate filesystems for automount scheme
|
|
"""
|
|
for line in scheme.split(';'):
|
|
source,mp = line.split(':')
|
|
if not source.startswith('/'):
|
|
if mp == "swap": yield "swap"
|
|
else: yield FileSystemManager.defaultFS['hdd']
|
|
|
|
def get(self):
|
|
scheme = self.Get('cl_autopartition_scheme')
|
|
device = self.Get('cl_autopartition_device')
|
|
if scheme and device:
|
|
return list(self.generateFormat(scheme))
|
|
return []
|
|
|
|
class VariableClAutopartitionDiskPart(ReadonlyVariable):
|
|
"""
|
|
Autopartition partition type (primary,extended,logical,gpt)
|
|
"""
|
|
type = "list"
|
|
|
|
def generatePart(self,scheme,dos):
|
|
"""
|
|
Generate part type for automount scheme
|
|
"""
|
|
number = 1
|
|
for line in scheme.split(';'):
|
|
sizeOrBind, mp = line.split(':')
|
|
if not sizeOrBind.startswith('/'):
|
|
if dos:
|
|
if number < 4: yield "primary"
|
|
else: yield "logical"
|
|
number += 1
|
|
else:
|
|
yield "gpt"
|
|
|
|
def get(self):
|
|
scheme = self.Get('cl_autopartition_scheme')
|
|
table = self.Get('cl_autopartition_table')
|
|
if scheme:
|
|
return list(self.generatePart(scheme,
|
|
self.Get('cl_autopartition_table')=='dos'))
|
|
return []
|
|
|
|
class VariableClAutopartitionDiskType(ReadonlyVariable):
|
|
"""
|
|
Autopartition partition scheme (simple - disk-partition)
|
|
"""
|
|
type = "list"
|
|
|
|
def get(self):
|
|
return map(lambda x:"disk-partition",
|
|
self.Get('cl_autopartition_disk_dev'))
|
|
|
|
class VariableClAutopartitionDiskSize(ReadonlyVariable):
|
|
"""
|
|
Autopartition disk size
|
|
"""
|
|
type = "list"
|
|
|
|
def generateSize(self,scheme,memory,rootsize):
|
|
args = {'memory':memory,
|
|
'rootsize': rootsize,
|
|
'allsize':"allfree"
|
|
}
|
|
for line in scheme.split(';'):
|
|
size,mp = line.split(':')
|
|
if not size.startswith('/'):
|
|
yield size.format(**args)
|
|
|
|
def get(self):
|
|
scheme = self.Get('cl_autopartition_scheme')
|
|
device = self.Get('cl_autopartition_device')
|
|
if scheme and device:
|
|
return list(self.generateSize(scheme,self.Get('hr_memory_size'),
|
|
str(int(self.Get('cl_autopartition_root_size'))
|
|
*1024*1024)))
|
|
return []
|
|
|
|
def humanReadable(self):
|
|
allSize = self.Get('cl_autopartition_free_size')
|
|
return map(humanreadableSize,
|
|
map(lambda x:allSize if x == "allfree" else x,
|
|
self.Get()))
|
|
|
|
class VariableClAutopartitionFreeSize(ReadonlyVariable):
|
|
"""
|
|
Freesize of device with current root_size and memory
|
|
"""
|
|
type = "int"
|
|
|
|
def get(self):
|
|
device = self.Get('cl_autopartition_device')
|
|
if not device:
|
|
return 0
|
|
sizeDevice = self.Select('os_device_size',
|
|
where='os_device_dev',
|
|
eq=device,limit=1)
|
|
sizes = self.Get('cl_autopartition_disk_size')
|
|
return reduce(lambda x,y: x - int(y) if y.isdigit() else x,
|
|
sizes,int(sizeDevice))
|
|
|
|
class VariableClAutopartitionBindData(ReadonlyVariable):
|
|
"""
|
|
Autopartition bind data
|
|
"""
|
|
type = "table"
|
|
source = ['cl_autopartition_bind_path',
|
|
'cl_autopartition_bind_mountpoint']
|
|
|
|
class VariableClAutopartitionBindPath(ReadonlyVariable):
|
|
"""
|
|
Autopartition bind points
|
|
"""
|
|
type = "list"
|
|
|
|
def generatePath(self,scheme):
|
|
for line in scheme.split(';'):
|
|
source,mp = line.split(':')
|
|
if source.startswith('/'):
|
|
yield source
|
|
|
|
def get(self):
|
|
scheme = self.Get('cl_autopartition_scheme')
|
|
device = self.Get('cl_autopartition_device')
|
|
return list(self.generatePath(scheme))
|
|
|
|
class VariableClAutopartitionBindMountpoint(ReadonlyVariable):
|
|
"""
|
|
Autopartition bind points
|
|
"""
|
|
type = "list"
|
|
|
|
def generateMountPoint(self,scheme):
|
|
for line in scheme.split(';'):
|
|
source,mp = line.split(':')
|
|
if source.startswith('/'):
|
|
yield mp
|
|
|
|
def get(self):
|
|
scheme = self.Get('cl_autopartition_scheme')
|
|
device = self.Get('cl_autopartition_device')
|
|
return list(self.generateMountPoint(scheme))
|