2019-11-04 23:18:28 -05:00
|
|
|
import re
|
|
|
|
##
|
|
|
|
import parted
|
|
|
|
import psutil
|
|
|
|
##
|
|
|
|
import aif.constants
|
|
|
|
import aif.disk._common
|
|
|
|
import aif.utils
|
2019-09-30 22:08:37 -04:00
|
|
|
|
2019-11-04 23:18:28 -05:00
|
|
|
_BlockDev = aif.disk._common.BlockDev
|
2019-11-03 01:40:23 -05:00
|
|
|
|
2019-11-04 23:18:28 -05:00
|
|
|
|
|
|
|
class Partition(object):
|
|
|
|
def __init__(self, part_xml, diskobj, start_sector, partnum, tbltype, part_type = None):
|
|
|
|
# Belive it or not, dear reader, but this *entire method* is just to set attributes.
|
|
|
|
if tbltype not in ('gpt', 'msdos'):
|
|
|
|
raise ValueError('{0} must be one of gpt or msdos'.format(tbltype))
|
|
|
|
if tbltype == 'msdos' and part_type not in ('primary', 'extended', 'logical'):
|
|
|
|
raise ValueError(('You must specify if this is a '
|
|
|
|
'primary, extended, or logical partition for msdos partition tables'))
|
|
|
|
aif.disk._common.addBDPlugin('part')
|
|
|
|
self.xml = part_xml
|
|
|
|
self.id = part_xml.attrib['id']
|
|
|
|
self.table_type = getattr(_BlockDev.PartTableType, tbltype.upper())
|
|
|
|
if tbltype == 'msdos':
|
|
|
|
# Could technically be _BlockDev.PartTypeReq.NEXT buuuut that doesn't *quite* work
|
|
|
|
# with our project's structure.
|
|
|
|
if part_type == 'primary':
|
|
|
|
self.part_type = _BlockDev.PartTypeReq.NORMAL
|
|
|
|
elif part_type == 'extended':
|
|
|
|
self.part_type = _BlockDev.PartTypeReq.EXTENDED
|
|
|
|
elif part_type == 'logical':
|
|
|
|
self.part_type = _BlockDev.PartTypeReq.LOGICAL
|
|
|
|
self.flags = []
|
|
|
|
for f in self.xml.findall('partitionFlag'):
|
|
|
|
# *Technically* we could use e.g. getattr(_BlockDev.PartFlag, f.text.upper()), *but* we lose compat
|
|
|
|
# with parted's flags if we do that. :| So we do some funky logic both here and in the constants.
|
|
|
|
if f.text in aif.constants.PARTED_BD_MAP:
|
|
|
|
flag_id = aif.constants.BD_PART_FLAGS_FLAG_IDX[aif.constants.PARTED_BD_MAP[f.text]]
|
|
|
|
elif f.text in aif.constants.BD_PART_FLAGS_FRIENDLY:
|
|
|
|
flag_id = aif.constants.BD_PART_FLAGS_FLAG_IDX[aif.constants.BD_PART_FLAGS_FRIENDLY[f.text]]
|
|
|
|
else:
|
|
|
|
continue
|
|
|
|
self.flags.append(_BlockDev.PartFlag(flag_id))
|
|
|
|
self.partnum = partnum
|
|
|
|
self.fstype = self.xml.attrib['fsType'].lower()
|
|
|
|
if self.fstype not in aif.constants.PARTED_FSTYPES: # There isn't a way to do this with BlockDev? :|
|
|
|
|
raise ValueError(('{0} is not a valid partition filesystem type; '
|
|
|
|
'must be one of: {1}').format(self.xml.attrib['fsType'],
|
|
|
|
', '.join(sorted(aif.constants.PARTED_FSTYPES))))
|
|
|
|
self.disk = diskobj
|
|
|
|
self.device = self.disk.device # TODO: how to get this in libblockdev?
|
|
|
|
self.devpath = '{0}{1}'.format(self.device.path, partnum)
|
|
|
|
self.is_hiformatted = False
|
|
|
|
sizes = {}
|
|
|
|
for s in ('start', 'stop'):
|
|
|
|
x = dict(zip(('from_bgn', 'size', 'type'),
|
|
|
|
aif.utils.convertSizeUnit(self.xml.attrib[s])))
|
|
|
|
sectors = x['size']
|
|
|
|
if x['type'] == '%':
|
|
|
|
sectors = int(self.device.getLength() / x['size'])
|
|
|
|
else:
|
|
|
|
sectors = int(aif.utils.size.convertStorage(x['size'],
|
|
|
|
x['type'],
|
|
|
|
target = 'B') / self.device.sectorSize)
|
|
|
|
sizes[s] = (sectors, x['from_bgn'])
|
|
|
|
if sizes['start'][1] is not None:
|
|
|
|
if sizes['start'][1]:
|
|
|
|
self.begin = sizes['start'][0] + 0
|
|
|
|
else:
|
|
|
|
self.begin = self.device.getLength() - sizes['start'][0] # TODO: is there a way to get this in BD?
|
|
|
|
else:
|
|
|
|
self.begin = sizes['start'][0] + start_sector
|
|
|
|
if sizes['stop'][1] is not None:
|
|
|
|
if sizes['stop'][1]:
|
|
|
|
self.end = sizes['stop'][0] + 0
|
|
|
|
else:
|
|
|
|
# This *technically* should be - 34, at least for gpt, but the alignment optimizer fixes it for us.
|
|
|
|
self.end = (self.device.getLength() - 1) - sizes['stop'][0] # TODO: is there a way to get this in BD?
|
|
|
|
else:
|
|
|
|
self.end = self.begin + sizes['stop'][0]
|
|
|
|
# TECHNICALLY we could craft the Geometry object with "length = ...", but it doesn't let us be explicit
|
|
|
|
# in configs. So we manually crunch the numbers and do it all at the end.
|
|
|
|
# TODO: switch parted objects to BlockDev
|
|
|
|
# self.geometry = parted.Geometry(device = self.device,
|
|
|
|
# start = self.begin,
|
|
|
|
# end = self.end)
|
|
|
|
# self.filesystem = parted.FileSystem(type = self.fstype,
|
|
|
|
# geometry = self.geometry)
|
|
|
|
# self.partition = parted.Partition(disk = diskobj,
|
|
|
|
# type = self.part_type,
|
|
|
|
# geometry = self.geometry,
|
|
|
|
# fs = self.filesystem)
|
|
|
|
self.part_name = self.xml.attrib.get('name')
|
|
|
|
|
|
|
|
#
|
|
|
|
# def detect(self):
|
|
|
|
# pass # TODO; blkinfo?
|
|
|
|
|
|
|
|
|
|
|
|
class Disk(object):
|
|
|
|
def __init__(self, disk_xml):
|
|
|
|
# TODO: BlockDev.part.set_disk_flag(<disk>,
|
|
|
|
# BlockDev.PartDiskFlag(1),
|
|
|
|
# True) ??
|
|
|
|
# https://lazka.github.io/pgi-docs/BlockDev-2.0/enums.html#BlockDev.PartDiskFlag
|
|
|
|
# https://unix.stackexchange.com/questions/325886/bios-gpt-do-we-need-a-boot-flag
|
|
|
|
self.xml = disk_xml
|
|
|
|
self.devpath = self.xml.attrib['device']
|
|
|
|
self.is_lowformatted = None
|
|
|
|
self.is_hiformatted = None
|
|
|
|
self.is_partitioned = None
|
|
|
|
self.partitions = None
|
|
|
|
self._initDisk()
|
|
|
|
aif.disk._common.addBDPlugin('part')
|
|
|
|
|
|
|
|
def _initDisk(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def diskFormat(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def getPartitions(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def partFormat(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class Mount(object):
|
|
|
|
def __init__(self, mount_xml, partobj):
|
|
|
|
pass
|
|
|
|
_common.addBDPlugin('fs')
|