From 12397e3dccf7ff6114dd1648ed10c5463857d308 Mon Sep 17 00:00:00 2001 From: Mike Hiretsky Date: Thu, 10 May 2012 11:48:34 +0400 Subject: [PATCH] Add lvm create method --- install/variables/autopartition.py | 119 +++++++++++++++++++++++------ install/variables/lvm.py | 84 ++++++++++++++++++++ install/variables/net.py | 17 +---- 3 files changed, 182 insertions(+), 38 deletions(-) create mode 100644 install/variables/lvm.py diff --git a/install/variables/autopartition.py b/install/variables/autopartition.py index b48a5c4..67f508f 100644 --- a/install/variables/autopartition.py +++ b/install/variables/autopartition.py @@ -107,14 +107,7 @@ class AutoPartition: fdisk.write(WRITE_AND_QUIT) fdisk.success() - for waittime in (0.1,0.2,0.5,1,2,4): - if path.exists(device[0]+str(num-1)): - return True - else: - sleep(waittime) - raise AutopartitionError( - _("Failed to found partition %s after creating partition table") - %dev) + self._waitDevice(device[0]+str(num-1)) def recreatePartitionTableGpt(self,device,data): """ @@ -151,14 +144,68 @@ class AutoPartition: fdisk.write(NEW_BIOSBOOT_PARTITION%"") fdisk.write(WRITE_AND_QUIT) fdisk.success() + self._waitDevice(device[0]+str(num-1)) + + def _waitDevice(self,device): for waittime in (0.1,0.2,0.5,1,2,4): - if path.exists(device[0]+str(num-1)): + if path.exists(device): return True else: sleep(waittime) raise AutopartitionError( _("Failed to found partition %s after creating partition table") - %dev) + %device) + + def _createPhisicalVolumes(self,devices): + pvCreateProg = getProgPath('/sbin/pvcreate') + return process(pvCreateProg,*devices).success() + + def _createVolumesGroup(self,vgname,disks): + vgCreateProg = getProgPath('/sbin/vgcreate') + return process(vgCreateProg,vgname,*disks).success() + + def _createLogicalVolume(self,vgname,lvname,size): + if size.isdigit(): + size = str(Sizes().to_K(int(size))) + if size == "allfree": + sizeparam = "-l100%FREE" + else: + sizeparam = "-L%sK"%size + lvCreateProg = getProgPath('/sbin/lvcreate') + return process(lvCreateProg,sizeparam,vgname,"-n",lvname).success() + + def _removeVolumeGroup(self,vgname): + vgRemoveProg = getProgPath('/sbin/vgremove') + return process(vgRemoveProg,vgname,"-f").success() + + def recreateLvm(self,table,devices,data,vgname): + """ + Create GPT partition table by /sbin/gdisk + """ + self._removeVolumeGroup(vgname) + for device in devices: + self.recreatePartitionTable(table,[device],[['','','','allfree']]) + + disks = map(lambda x:"%s1"%x,devices) + if not self._createPhisicalVolumes(disks): + raise AutopartitionError( + _("Failed to create phisical volumes from %s") + %",".join(devices)) + + if not self._createVolumesGroup(vgname,disks): + raise AutopartitionError( + _("Failed to create volumes group {groupname} from {disks}") + .format(groupname=vgname, + disks=",".join(devices))) + + lvCreateProg = getProgPath('/sbin/lvcreate') + for disk,size in map(operator.itemgetter(0,3),data): + lvname = disk.rpartition('/')[2] + if not self._createLogicalVolume(vgname,lvname,size): + raise AutopartitionError( + _("Failed to create logical volume {name}") + .format(name=lvname)) + self._waitDevice('/dev/%s/root'%vgname) class AutopartitionHelper: """ @@ -280,10 +327,15 @@ class VariableClAutopartitionDevice(AutopartitionHelper,Variable): useDisks = self.Select('os_disk_parent', where='os_disk_mount', ne='') - for value in valuelist: - if value in useDisks: - raise VariableError( - _("Device %s already is used by current system")%value) + #for value in valuelist: + # if value in useDisks: + # raise VariableError( + # _("Device %s already is used by current system")%value) + if len(valuelist) > 1 and \ + self.Get('cl_autopartition_lvm_set') == 'off': + raise VariableError( + _("You should use LVM for installation on " + "more that one device")) freeSize = int(self.Get('cl_autopartition_free_size')) if freeSize < 0 and (abs(freeSize))/(Sizes.M*100) > 0: availSize = int(self.Get('cl_autopartition_device_size')) @@ -329,6 +381,7 @@ class VariableClAutopartitionScheme(AutopartitionHelper,Variable,AutoPartition): ("data",_("/var/calculate partition")), ("home",_("Mount /var/calculate/home to /home")), ("boot",_("Separate boot partition")), + ("lvm",_("Use LVM")) ] class VariableClAutopartitionRootSize(AutopartitionHelper,Variable): @@ -406,8 +459,17 @@ class VariableClAutopartitionDiskData(ReadonlyTableVariable): 'cl_autopartition_disk_mount', 'cl_autopartition_disk_format', 'cl_autopartition_disk_size', - 'cl_autopartition_disk_part'] + 'cl_autopartition_disk_part', + 'cl_autopartition_disk_name'] +class VariableClAutopartitionLvmSet(ReadonlyVariable): + """ + Using LVM for autopartition + """ + type = "bool" + + def get(self): + return "on" if "lvm" in self.Get('cl_autopartition_scheme') else "off" class VariableClAutopartitionDiskDev(ReadonlyVariable,AutopartitionHelper): """ @@ -415,7 +477,7 @@ class VariableClAutopartitionDiskDev(ReadonlyVariable,AutopartitionHelper): """ type = "list" - def generateDisks(self,dos,device,scheme,number=0): + def generateDisks(self,dos=False,devices=[],scheme=[],number=0): """ Generate disks for automount scheme """ @@ -425,17 +487,30 @@ class VariableClAutopartitionDiskDev(ReadonlyVariable,AutopartitionHelper): # for gpt 4 - for bios_boot if number == 4: number += 1 - yield "%s%d"%(device,number) + yield "%s%d"%(devices[0],number) number += 1 + def generateLvm(self,scheme=[],devices=[],**kwargs): + for line in map(lambda x:{'root':'root2', + 'root2':'root'}.get(x,x), + self.deviceOpts(scheme)): + yield "/dev/calculate/%s"%line + + def diskGenerator(self): + if self.Get('cl_autopartition_lvm_set') == 'on': + return self.generateLvm + else: + return self.generateDisks + def get(self): if self.Get('cl_autopartition_set') == "auto": scheme = self.getAutopartitionScheme() - device = self.Get('cl_autopartition_device') - if device: - res = list(self.generateDisks( - self.Get('cl_autopartition_table')=='dos', - device[0],scheme)) + devices = self.Get('cl_autopartition_device') + if devices: + res = list(self.diskGenerator()( + devices=devices, + scheme=scheme, + dos=self.Get('cl_autopartition_table')=='dos')) return res return [] diff --git a/install/variables/lvm.py b/install/variables/lvm.py new file mode 100644 index 0000000..bcc397e --- /dev/null +++ b/install/variables/lvm.py @@ -0,0 +1,84 @@ +#-*- 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 +import pty,fcntl +from subprocess import Popen +from os import path +from itertools import * +from calculate.lib.datavars import (TableVariable,Variable,VariableError, + ReadonlyVariable,ReadonlyTableVariable, + FieldValue) +from calculate.lib.utils.files import (process,checkUtils) +from calculate.install.cl_distr import PartitionDistributive +from calculate.install.fs_manager import FileSystemManager + +from calculate.lib.cl_lang import setLocalTranslate +setLocalTranslate('cl_install3',sys.modules[__name__]) + +####################################################### +# Devices variables +####################################################### +class VariableOsLvmData(ReadonlyTableVariable): + """ + Information about disk devices + """ + type = 'table' + source = ['os_lvm_lvname', + 'os_lvm_vgname', + 'os_lvm_pvname'] + + def getLvmData(self): + """Get route table, exclude specifed iface""" + pvDisplayProg = checkUtils('/sbin/pvdisplay') + pvDisplay = process(pvDisplayProg,"--noh","-Co", + "lv_name,vg_name,pv_name") + for line in pvDisplay: + line = line.split() + if len(line) == 3: + yield line + + def get(self,hr=False): + """LVM hash""" + return list(self.getLvmData()) or [[]] + + setValue = Variable.setValue + +class VariableOsLvmLvname(FieldValue,ReadonlyVariable): + """ + Logical volumes names + """ + type = "list" + source_variable = "os_lvm_data" + column = 0 + +class VariableOsLvmVgname(FieldValue,ReadonlyVariable): + """ + Volume groups names + """ + type = "list" + source_variable = "os_lvm_data" + column = 1 + +class VariableOsLvmPvname(FieldValue,ReadonlyVariable): + """ + Phisical volumes names + """ + type = "list" + source_variable = "os_lvm_data" + column = 2 diff --git a/install/variables/net.py b/install/variables/net.py index a7872c7..bcff655 100644 --- a/install/variables/net.py +++ b/install/variables/net.py @@ -19,7 +19,7 @@ import sys import re from os import path from calculate.lib.datavars import Variable,VariableError,ReadonlyVariable, \ - READONLY, TableVariable + READONLY, TableVariable,FieldValue from calculate.lib.cl_lang import setLocalTranslate setLocalTranslate('cl_install3',sys.modules[__name__]) @@ -33,21 +33,6 @@ from calculate.lib.utils.portage import isPkgInstalled from operator import itemgetter from itertools import * -class FieldValue: - """ - Table column variable - """ - type = "list" - source_variable = "" - column = 0 - - def get(self): - sourceVar = self.Get(self.source_variable) - if any(sourceVar): - return zip(*sourceVar)[self.column] - else: - return [] - class NetHelper: """ Network variables not using for flash installation