modified: interface/ri_data.py
remove MountPoint use new datastructure for instead
modified: interface/ri_install.py
add MakePartitions for partition
modified: interface/ri_oper.py
1.add MakePartitions class
2.modify Format, Mount, ConfigureFstab class
modified: new_partition/partition_data.py
1.add disk_from_os attribute to Partition class for disk
2.add process linux-swap(v1) in Partition class
3.force convert num and sn to int, beacause when read from install.xml
sn and num is still string.
modified: operation/format_partition.sh
1.add timeout beacause use MakePartitions, need time to generate
device file
2.add linux-swap for swap
modified: operation/functions
1.add % support, beacause of partition may use 1% to partition
disks.
new file: operation/partition_disks.sh
1.use partition_disks as parted stdin wrapper.
Signed-off-by: Qin Bo <bqin@linx-info.com>
454 lines
16 KiB
Python
Executable File
454 lines
16 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
import re,os
|
|
import commands
|
|
import subprocess
|
|
import signal
|
|
from xml.dom import minidom
|
|
from collections import defaultdict
|
|
import _ped
|
|
import parted_devices
|
|
|
|
if os.environ.get('DEBUG'):
|
|
DEBUG = True
|
|
else:
|
|
DEBUG = False
|
|
|
|
''' algorithm from libparted/unit.c '''
|
|
def parse_unit_suffix(suffix):
|
|
if (len(suffix) > 1) and (suffix[1] == 'i'):
|
|
return {
|
|
'k': _ped.UNIT_KIBIBYTE,
|
|
'm': _ped.UNIT_MEBIBYTE,
|
|
'g': _ped.UNIT_GIBIBYTE,
|
|
't': _ped.UNIT_TEBIBYTE,
|
|
}[suffix[0].lower()]
|
|
elif (len(suffix) > 0):
|
|
return {
|
|
's': _ped.UNIT_SECTOR,
|
|
'b': _ped.UNIT_BYTE,
|
|
'k': _ped.UNIT_KILOBYTE,
|
|
'm': _ped.UNIT_MEGABYTE,
|
|
'g': _ped.UNIT_GIGABYTE,
|
|
't': _ped.UNIT_TERABYTE,
|
|
'c': _ped.UNIT_CYLINDER,
|
|
'%': _ped.UNIT_PERCENT,
|
|
}[suffix[0].lower()]
|
|
|
|
''' type name for display '''
|
|
def get_type_name(type):
|
|
try: return {
|
|
_ped.PARTITION_NORMAL :'primary',
|
|
_ped.PARTITION_LOGICAL :'logical',
|
|
_ped.PARTITION_EXTENDED :'extended',
|
|
_ped.PARTITION_FREESPACE :' ',
|
|
_ped.PARTITION_METADATA :' ',
|
|
_ped.PARTITION_PROTECTED :' ',
|
|
}[type]
|
|
except KeyError:
|
|
return ' '
|
|
|
|
''' get_flags from rhel5 anaconda partedUtils.py
|
|
algorithm the same as parted in parted.c partition_print_flags() '''
|
|
def get_flags (part):
|
|
string=""
|
|
if not part.is_active ():
|
|
return string
|
|
first=1
|
|
flag = _ped.partition_flag_next (0)
|
|
while flag:
|
|
if part.get_flag (flag):
|
|
string = string + _ped.partition_flag_get_name (flag)
|
|
if first:
|
|
first = 0
|
|
else:
|
|
string = string + ", "
|
|
flag = _ped.partition_flag_next (flag)
|
|
return string
|
|
|
|
|
|
'''make nested dict'''
|
|
def makehash():
|
|
return defaultdict(makehash)
|
|
|
|
class Partition:
|
|
''' disk partition '''
|
|
unit = ''
|
|
dict = makehash()
|
|
''' Partition init function '''
|
|
def __init__(self, dev, ds, pt, dfm, sn, partition, num, st, se, sz, tp, fs, fg, fr, fm, mp):
|
|
|
|
'''special process linux-swap(v1) use linux-swap for instead '''
|
|
if fs.startswith('linux-swap'):
|
|
fs = 'linux-swap'
|
|
self.dict[dev][dev] = dev
|
|
self.dict[dev]['disk_size'] = ds
|
|
self.dict[dev]['partition_table'] = pt
|
|
''' if modify parittion table this flag is no '''
|
|
self.dict[dev]['from_os'] = dfm
|
|
self.dict[dev]['partition'][partition]['sn']= sn
|
|
self.dict[dev]['partition'][partition]['num']= num
|
|
self.dict[dev]['partition'][partition]['start'] = st
|
|
self.dict[dev]['partition'][partition]['end'] = se
|
|
self.dict[dev]['partition'][partition]['size'] = sz
|
|
self.dict[dev]['partition'][partition]['type'] = tp
|
|
self.dict[dev]['partition'][partition]['filesystem'] = fs
|
|
self.dict[dev]['partition'][partition]['flags'] = fg
|
|
self.dict[dev]['partition'][partition]['from_os'] = fr
|
|
self.dict[dev]['partition'][partition]['format'] = fm
|
|
self.dict[dev]['partition'][partition]['mount_point'] = mp
|
|
|
|
@staticmethod
|
|
def get_disks():
|
|
return parted_devices.get_disks()
|
|
|
|
@staticmethod
|
|
def check_partitions():
|
|
cmd = "grep [a-zA-Z][0-9] /proc/partitions>/dev/null"
|
|
ret = os.system(cmd)
|
|
return ret
|
|
|
|
@staticmethod
|
|
def init_from_os(unit='b'):
|
|
|
|
Partition.unit = unit
|
|
|
|
if Partition.unit:
|
|
default_unit = parse_unit_suffix(Partition.unit)
|
|
else:
|
|
default_unit = _ped.UNIT_COMPACT
|
|
_ped.unit_set_default(default_unit)
|
|
|
|
''' each disk '''
|
|
for d in Partition.get_disks():
|
|
_device = _ped.device_get(d)
|
|
try:
|
|
_disk = _ped.Disk(_device)
|
|
except:
|
|
continue
|
|
_part = _disk.next_partition()
|
|
''' free partition number '''
|
|
fn = 0
|
|
''' partition sequence number '''
|
|
sn = 0
|
|
''' each partition '''
|
|
|
|
''' algorithm from parted.c do_print() '''
|
|
disk_start = _device.unit_format (0)
|
|
disk_end = _device.unit_format_byte (_device.length * _device.sector_size \
|
|
- (default_unit == _ped.UNIT_CHS or \
|
|
default_unit == _ped.UNIT_CYLINDER))
|
|
|
|
disk_size = disk_end
|
|
|
|
partition_table = _disk.type.name
|
|
dev = _device.path
|
|
|
|
if DEBUG:
|
|
print dev
|
|
print partition_table
|
|
print disk_start
|
|
print disk_size
|
|
while _part:
|
|
|
|
''' skip _part.type = 9
|
|
I can't find type 9 from pyparted '''
|
|
if _part.type == 9:
|
|
_part = _disk.next_partition(_part)
|
|
continue
|
|
|
|
p_g = _part.geom
|
|
|
|
''' algorithm get from parted.c do_print() '''
|
|
start = _device.unit_format(p_g.start)
|
|
end = _device.unit_format_byte((p_g.end + 1) * _device.sector_size - 1)
|
|
size = _device.unit_format(p_g.length)
|
|
|
|
if _part.num == -1:
|
|
fn += 1
|
|
num = fn
|
|
partition = "free %s" %fn
|
|
else:
|
|
num = _part.num
|
|
partition = _part.get_path()
|
|
|
|
type_name = get_type_name(_part.type)
|
|
|
|
try:
|
|
fs = _part.fs_type.name
|
|
except:
|
|
fs = ' '
|
|
''' may be PARTITION_METADATA mustn't appear at free space,
|
|
but may be pyparted have bug, awareness last partition as
|
|
metadata. But parted is not. '''
|
|
if _part.type & _ped.PARTITION_FREESPACE or \
|
|
_part.type & _ped.PARTITION_METADATA:
|
|
fs = 'Free Space'
|
|
|
|
flags = get_flags(_part)
|
|
|
|
sn += 1
|
|
|
|
if DEBUG:
|
|
print "sn:%s, num:%s, %s, start:%s, end:%s, size:%s,\
|
|
type_name:%s, fs: %s, flags: %s" %(sn, num, partition, start, end, size, \
|
|
type_name, fs, flags)
|
|
|
|
''' create a Partition instance from hardware info '''
|
|
Partition(dev , # device name
|
|
disk_size, # disk size
|
|
partition_table, # partition table
|
|
'yes', # disk from os
|
|
sn, # partition sequence number
|
|
partition, # partition
|
|
num, # num
|
|
start, # start
|
|
end, # end
|
|
size, # size
|
|
type_name, # type
|
|
fs, # file system
|
|
flags, # flags
|
|
'yes', # partition from os
|
|
' ', # whether format
|
|
' ' # mount point
|
|
)
|
|
|
|
''' next partition '''
|
|
_part = _disk.next_partition(_part)
|
|
|
|
@staticmethod
|
|
def init_from_xml(node):
|
|
''' create Partition instances from xml node '''
|
|
Partition.unit = node.attributes['unit'].value.encode('ascii')
|
|
if DEBUG:
|
|
print Partition.unit
|
|
for d in node.childNodes:
|
|
if d.nodeType == node.ELEMENT_NODE and d.nodeName == 'disk':
|
|
dev = d.attributes['disk'].value.encode('ascii')
|
|
disk_size = d.attributes['disk_size'].value.encode('ascii')
|
|
partition_table = d.attributes['partition_table'].value.encode('ascii')
|
|
disk_from_os = d.attributes['from_os'].value.encode('ascii')
|
|
|
|
if DEBUG:
|
|
print dev
|
|
print partition_table
|
|
print disk_size
|
|
print disk_from_os
|
|
|
|
for p in d.getElementsByTagName('partition'):
|
|
sn = p.attributes['sn'].value.encode('ascii')
|
|
partition = p.attributes['partition'].value.encode('ascii')
|
|
num = p.attributes['num'].value.encode('ascii')
|
|
start = p.attributes['start'].value.encode('ascii')
|
|
end = p.attributes['end'].value.encode('ascii')
|
|
size = p.attributes['size'].value.encode('ascii')
|
|
type_name = p.attributes['type'].value.encode('ascii')
|
|
fs = p.attributes['filesystem'].value.encode('ascii')
|
|
flags = p.attributes['flags'].value.encode('ascii')
|
|
from_os = p.attributes['from_os'].value.encode('ascii')
|
|
fmt = p.attributes['format'].value.encode('ascii')
|
|
mp = p.attributes['mount_point'].value.encode('ascii')
|
|
|
|
if DEBUG:
|
|
print "sn:%s, num:%s, %s, start:%s, end:%s, size:%s,\
|
|
type_name:%s, fs: %s, flags: %s" %(sn, num, partition, start, end, size, \
|
|
type_name, fs, flags)
|
|
|
|
''' initialise from xml '''
|
|
Partition(dev , # device name
|
|
disk_size, # disk size
|
|
partition_table, # partition table
|
|
disk_from_os, # disk from os
|
|
sn, # partition sequence number
|
|
partition, # partition
|
|
num, # num
|
|
start, # start
|
|
end, # end
|
|
size, # size
|
|
type_name, # type
|
|
fs, # file system
|
|
flags, # flags
|
|
from_os, # from os
|
|
fmt, # whether format
|
|
mp # mount point
|
|
)
|
|
|
|
|
|
@staticmethod
|
|
def to_xml(doc, p_node):
|
|
''' write all Partition instance into xml
|
|
doc - xml document instance
|
|
p_node - xml node (parent node)'''
|
|
pts = doc.createElement('disks')
|
|
unit_attr = doc.createAttribute('unit')
|
|
unit_attr.value = Partition.unit
|
|
pts.setAttributeNode(unit_attr)
|
|
|
|
create_node(Partition.dict, doc, pts)
|
|
p_node.appendChild(pts)
|
|
p_node.appendChild(pts)
|
|
|
|
@staticmethod
|
|
def get_disk_attr(disk, attr):
|
|
try:
|
|
return Partition.dict[disk][attr]
|
|
except:
|
|
return None
|
|
|
|
@staticmethod
|
|
def get_partition_attr(partition, attr):
|
|
disk = re.sub("\d+$", "", partition)
|
|
try:
|
|
return Partition.dict[disk]['partition'][partition][attr]
|
|
except:
|
|
return None
|
|
|
|
@staticmethod
|
|
def get_raid_devices():
|
|
rd = []
|
|
for key in Partition.dict:
|
|
for k in Partition.dict[key]['partition'].keys():
|
|
if Partition.dict[key]['partition'][k]['flags'] == 'raid':
|
|
rd.append(k)
|
|
|
|
return rd
|
|
|
|
''' Fix Me:
|
|
make recursive is better '''
|
|
def create_node(d, doc, pts):
|
|
for key in d.keys():
|
|
dt = doc.createElement('disk')
|
|
dt.setAttribute('disk', key)
|
|
for k in d[key].keys():
|
|
if k == 'partition':
|
|
pt = doc.createElement('partitions')
|
|
for l in d[key]['partition'].keys():
|
|
lt = doc.createElement('partition')
|
|
lt.setAttribute('partition', str(l))
|
|
for m in d[key]['partition'][l].keys():
|
|
'''if mount_point etc. is ' ', then can't set attribute,
|
|
so I manual add space
|
|
'''
|
|
attr = "%s " %d[key]['partition'][l][m]
|
|
if attr.rstrip():
|
|
attr = attr.rstrip()
|
|
lt.setAttribute(m, attr)
|
|
pt.appendChild(lt)
|
|
dt.appendChild(pt)
|
|
elif k == 'disk_size':
|
|
dt.setAttribute(str(k), d[key]['disk_size'])
|
|
elif k == 'partition_table':
|
|
dt.setAttribute(str(k), d[key]['partition_table'])
|
|
elif k == 'from_os':
|
|
dt.setAttribute(str(k), d[key]['from_os'])
|
|
pts.appendChild(dt)
|
|
|
|
def pretty(d, indent=0):
|
|
for key, value in d.iteritems():
|
|
print '\t' * indent + str(key)
|
|
if isinstance(value, dict):
|
|
pretty(value, indent+1)
|
|
else:
|
|
print '\t' * (indent+1) + str(value)
|
|
|
|
def delete_all_partitions(d, k):
|
|
for key in d[k]['partition'].keys():
|
|
d[k]['partition'].pop(key, None)
|
|
|
|
partition = 'free 1'
|
|
sz = se = d[k]['disk_size']
|
|
d[k]['partition'][partition]['sn']= 1
|
|
d[k]['partition'][partition]['num']= 1
|
|
d[k]['partition'][partition]['start'] = '0'
|
|
d[k]['partition'][partition]['end'] = se
|
|
d[k]['partition'][partition]['size'] = sz
|
|
d[k]['partition'][partition]['type'] = ''
|
|
d[k]['partition'][partition]['filesystem'] = ''
|
|
d[k]['partition'][partition]['flags'] = ''
|
|
d[k]['partition'][partition]['from_os'] = ''
|
|
d[k]['partition'][partition]['format'] = ''
|
|
d[k]['partition'][partition]['mount_point'] = ''
|
|
|
|
def delete_one_partition(dict, disk, partition):
|
|
for key in dict[disk]['partition'].keys():
|
|
if key == partition:
|
|
del dict[disk]['partition'][key]
|
|
|
|
def sort_partition(dict, disk, p):
|
|
f_d = {}
|
|
p_d = {}
|
|
|
|
for k in dict[disk]["partition"]:
|
|
if k.startswith("free"):
|
|
f_d[k] = int(dict[disk]["partition"][k]["num"])
|
|
else:
|
|
p_d[k] = int(dict[disk]["partition"][k]["num"])
|
|
|
|
if p == "free":
|
|
return (sorted(f_d, key = lambda key: f_d[key]))
|
|
elif p == "partition":
|
|
return (sorted(p_d, key = lambda key: p_d[key]))
|
|
else:
|
|
return
|
|
|
|
def sort_partitions(dict, disk, p="all"):
|
|
if p == "all":
|
|
''' k, t: partitions '''
|
|
return (sorted(((k) for k in dict[disk]["partition"]), key=lambda \
|
|
t: int(dict[disk]["partition"][t]["sn"])))
|
|
elif p == "free":
|
|
return sort_partition(dict, disk, "free")
|
|
elif p == "partition":
|
|
return sort_partition(dict, disk, "partition")
|
|
|
|
def write_to_xml_file():
|
|
xmldoc = minidom.Document()
|
|
root = xmldoc.createElement('install')
|
|
xmldoc.appendChild(root)
|
|
Partition.to_xml(xmldoc, root)
|
|
xml_string =xmldoc.toprettyxml(indent=" ")
|
|
print xml_string
|
|
|
|
def init_from_xml():
|
|
xmldoc = minidom.parse('install.xml')
|
|
root = xmldoc.firstChild
|
|
for n in root.childNodes:
|
|
if n.nodeType == n.ELEMENT_NODE:
|
|
if n.nodeName == 'disks':
|
|
Partition.init_from_xml(n)
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
Partition.init_from_os()
|
|
#for d in Partition.get_raid_devices():
|
|
# print d
|
|
#print Partition.dict.keys()
|
|
pretty(Partition.dict)
|
|
#print Partition.unit
|
|
#write_to_xml_file()
|
|
#disks = Partition.dict.keys()
|
|
#disks.sort()
|
|
#for key in disks:
|
|
# partitions = sort_partitions(Partition.dict, key, 'partition')
|
|
# for p in partitions:
|
|
# for k in Partition.dict[key]['partition'].keys():
|
|
# if k == p:
|
|
# print "%s, %s, %s" %(key, k, Partition.dict[key]['partition'][k]['filesystem'])
|
|
#init_from_xml()
|
|
#pretty(Partition.dict)
|
|
#delete_all_partitions(Partition.dict, "/dev/sda")
|
|
#delete_one_partition(Partition.dict, "/dev/sdb", "free 1")
|
|
#pretty(Partition.dict)
|
|
#print sort_partitions(Partition.dict, "/dev/sda", "all")
|
|
#print "+"*100
|
|
#print sort_partitions(Partition.dict, "/dev/sda", "free")
|
|
#print "+"*100
|
|
#print sort_partitions(Partition.dict, "/dev/sda", "partition")
|
|
#print Partition.dict
|
|
#print Partition.get_size("/dev/sda")
|
|
#print Partition.get_disk_attr("/dev/sda", "disk_size")
|
|
#print Partition.get_disk_attr("/dev/sda", "partition_table")
|
|
#print Partition.get_partition_attr("/dev/sda1", "size")
|
|
|