def get_all_remaining_geom(self, disk, device, start): # See if there is a part after this for part in disk.partitions: geom = part.geometry if self.part_offset < geom.start: length = geom.end - self.part_offset length -= parted.sizeToSectors(1, 'MB', device.sectorSize) return parted.Geometry( device=device, start=start, length=length) length = device.getLength() - start length -= parted.sizeToSectors(1, 'MB', device.sectorSize) return parted.Geometry(device=device, start=start, length=length)
def revertRepartition(device, partition, deltastart, deltaend, unit='MiB'): dev = parted.getDevice(device) disk = parted.newDisk(dev) targetPartition = disk.getPartitionByPath(device + partition) geometry = targetPartition.geometry geometry.start += parted.sizeToSectors(deltastart, unit, dev.sectorSize) geometry.end += parted.sizeToSectors(deltaend, unit, dev.sectorSize) disk.deletePartition(targetPartition) partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=geometry) disk.addPartition(partition=partition, constraint=dev.optimalAlignedConstraint) disk.commit()
def _parse_last_sector_expr(self, start, value, sector_size): """Parses fdisk(1)-style partition end exception""" import re # map fdisk units to PyParted ones known_units = {'K': 'KiB', 'M': 'MiB', 'G': 'GiB', 'KB': 'kB', 'MB': 'MB', 'GB': 'GB'} match = re.search('^\+(?P<num>\d+)(?P<unit>[KMG]?)$', value) if match: # num must be an integer; if not, raise ValueError num = int(match.group('num')) unit = match.group('unit') if not unit: # +sectors sector = start + num return sector elif unit in known_units.keys(): # +size{K,M,G} sector = start + \ parted.sizeToSectors(num, known_units[unit], sector_size) return sector else: # must be an integer (sector); if not, raise ValueError sector = int(value) return sector
def apply(self, disk, simulate): """ Create a partition with the given type... """ try: if not disk: raise RuntimeError("Cannot create partition on empty disk!") length = parted.sizeToSectors(self.size, 'B', disk.device.sectorSize) geom = parted.Geometry(device=self.device, start=self.part_offset, length=length) # Don't run off the end of the disk ... geom_cmp = self.get_all_remaining_geom(disk, disk.device, self.part_offset) if geom_cmp.length < geom.length or geom.length < 0: geom = geom_cmp if "LVM" in self.fstype: fs = None else: fs = parted.FileSystem(type=self.fstype, geometry=geom) p = parted.Partition(disk=disk, type=self.ptype, fs=fs, geometry=geom) disk.addPartition(p, parted.Constraint(device=self.device)) self.part = p self.part_end = self.part_offset + length except Exception as e: self.set_errors(e) return False return True
def shrinkpart(part, size): dsk = part.disk dev = dsk.device print('Resizing partition...') # Create a new geometry newgeo = parted.Geometry(start=part.geometry.start, length=parted.sizeToSectors( shrink_to, 'B', dev.sectorSize), device=dev) logging.DEBUG(newgeo.__str__()) # Create a new partition with our new geometry newpart = parted.Partition(disk=dsk, type=parted.PARTITION_NORMAL, geometry=newgeo) # Create a constraint that aligns our new geometry with the optimal alignment of the disk constraint = parted.Constraint(maxGeom=newgeo).intersect( dev.optimalAlignedConstraint) dsk.deletePartition(part) dsk.addPartition(partition=newpart, constraint=constraint) try: dsk.commit() except: pass return (newgeo.end + 1) * dev.sectorSize
def apply(self, disk, simulate): """ Create a partition with the given type... """ try: if not disk: raise RuntimeError("Cannot create partition on empty disk!") length = parted.sizeToSectors( self.size, 'B', disk.device.sectorSize) geom = parted.Geometry( device=self.device, start=self.part_offset, length=length) # Don't run off the end of the disk ... geom_cmp = self.get_all_remaining_geom( disk, disk.device, self.part_offset) if geom_cmp.length < geom.length or geom.length < 0: geom = geom_cmp fs = parted.FileSystem(type=self.fstype, geometry=geom) p = parted.Partition( disk=disk, type=self.ptype, fs=fs, geometry=geom) disk.addPartition( p, parted.Constraint(device=self.device)) self.part = p self.part_end = self.part_offset + length except Exception as e: self.set_errors(e) return False return True
def gpt_easyhandler(dev, disk, start, end, number): fs = "ext4" bios_grub = False for p in disk.partitions: if p.number != number and p.getFlag(parted.PARTITION_BIOS_GRUB): bios_grub = True break if bios_grub and number > 0: return [disk, number] if bios_grub == False: if number > 0: disk = rfparted.rmpart(disk, number) size = parted.sizeToSectors(1, "MB", 512) disk = rfparted.mkpart(dev, disk, "primary", start, size, end, "bios_grub") start = start + size + 1 partnumber = [part.number for part in disk.partitions] disk = rfparted.mkpart(dev, disk, "primary", start, 0, end, fs) number = 0 for p in disk.partitions: if p.number in partnumber: continue number = p.number break return [disk, number]
def shrinkpart(part, size): dsk = part.disk dev = dsk.device print('Resizing partition...') # Create a new geometry newgeo = parted.Geometry(start=part.geometry.start, length=parted.sizeToSectors( size, 'B', dev.sectorSize), device=dev) # logging.DEBUG(newgeo.__str__()) # Create a new partition with our new geometry newpart = parted.Partition(disk=dsk, type=parted.PARTITION_NORMAL, geometry=newgeo) # Create a constraint that aligns our new geometry with the optimal alignment of the disk constraint = parted.Constraint(maxGeom=newgeo).intersect( dev.optimalAlignedConstraint) dsk.deletePartition(part) dsk.addPartition(partition=newpart, constraint=constraint) # This exception gets raised even though dsk.commit() seems to do its job just fine. # I am definitely not a fan of doing this, but so be it. try: dsk.commit() except parted._ped.IOException: pass return (newgeo.end + 1) * dev.sectorSize
def _parse_last_sector_expr(self, start, value, sector_size): """Parses fdisk(1)-style partition end exception""" import re # map fdisk units to PyParted ones known_units = {'K': 'KiB', 'M': 'MiB', 'G': 'GiB', 'KB': 'kB', 'MB': 'MB', 'GB': 'GB'} match = re.search('^\+(?P<num>\d+)(?P<unit>[KMG]?)$', value) if match: # num must be an integer; if not, raise ValueError num = int(match.group('num')) unit = match.group('unit') if not unit: # +sectors sector = start + num return sector elif unit in known_units.keys(): # +size{K,M,G} sector = start + parted.sizeToSectors(num, known_units[unit], sector_size) return sector else: # must be an integer (sector); if not, raise ValueError sector = int(value) return sector
def partition(diskname, specs, force=False, check_mode=False): """ Create requested partitions. Returns nr. of created partitions or 0 when the disk was already partitioned. """ count = 0 dev = parted.getDevice(diskname) try: disk = parted.newDisk(dev) except parted.DiskException: # unrecognizable format, treat as empty disk disk = None if disk and len(disk.partitions) > 0 and not force: print "skipping", diskname return 0 # create new partition table, wiping all existing data disk = parted.freshDisk(dev, 'gpt') # calculate nr. of partitions of each size assign_space(dev.getSize(), specs) last_megabyte = 1 for spec in specs: for _ in range(spec.count): # create the partition start = parted.sizeToSectors(last_megabyte, "MiB", dev.sectorSize) length = parted.sizeToSectors(spec.size, "MiB", dev.sectorSize) geo = parted.Geometry(device=dev, start=start, length=length) filesystem = parted.FileSystem(type='ext4', geometry=geo) part = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=filesystem, geometry=geo) disk.addPartition(partition=part, constraint=dev.optimalAlignedConstraint) last_megabyte += spec.size count += 1 try: if not check_mode: disk.commit() except parted.IOException: # partitions have been written, but we have been unable to inform the # kernel of the change, probably because they are in use. # Ignore it and hope for the best... pass return count
def partition(diskname, specs, force=False, check_mode=False): """ Create requested partitions. Returns nr. of created partitions or 0 when the disk was already partitioned. """ count = 0 dev = parted.getDevice(diskname) try: disk = parted.newDisk(dev) except parted.DiskException: # unrecognizable format, treat as empty disk disk = None if disk and len(disk.partitions) > 0 and not force: print "skipping", diskname return 0 # create new partition table, wiping all existing data disk = parted.freshDisk(dev, 'gpt') # calculate nr. of partitions of each size assign_space(dev.getSize(), specs) last_megabyte = 1 for spec in specs: for _ in range(spec.count): # create the partition start = parted.sizeToSectors(last_megabyte, "MiB", dev.sectorSize) length = parted.sizeToSectors(spec.size, "MiB", dev.sectorSize) geo = parted.Geometry(device=dev, start=start, length=length) filesystem = parted.FileSystem(type='ext4', geometry=geo) part = parted.Partition( disk=disk, type=parted.PARTITION_NORMAL, fs=filesystem, geometry=geo) disk.addPartition(partition=part, constraint=dev.optimalAlignedConstraint) last_megabyte += spec.size count += 1 try: if not check_mode: disk.commit() except parted.IOException: # partitions have been written, but we have been unable to inform the # kernel of the change, probably because they are in use. # Ignore it and hope for the best... pass return count
def _compute_geometries(device): sectorSize = device.sectorSize esp = parted.Geometry(device=device, start=parted.sizeToSectors(8, "MB", sectorSize), length=parted.sizeToSectors(550, "MB", sectorSize)) data = parted.Geometry(device=device, start=esp.end + 1, length=parted.sizeToSectors(PARTITION_SIZE_GB_DATA, "GB", sectorSize)) systemA = parted.Geometry(device=device, start=data.end + 1, length=parted.sizeToSectors( PARTITION_SIZE_GB_SYSTEM, "GB", sectorSize)) systemB = parted.Geometry(device=device, start=systemA.end + 1, length=parted.sizeToSectors( PARTITION_SIZE_GB_SYSTEM, "GB", sectorSize)) return {'esp': esp, 'data': data, 'systemA': systemA, 'systemB': systemB}
def raw_format(device_path, fstype, volume_label): do_umount(device_path) # First erase MBR and partition table , if any os.system("dd if=/dev/zero of=%s bs=512 count=1 >/dev/null 2>&1" % device_path) device = parted.getDevice(device_path) # Create a default partition set up disk = parted.freshDisk(device, 'msdos') disk.commit() regions = disk.getFreeSpaceRegions() if len(regions) > 0: #print "Build partition" # Define size region = regions[-1] start = parted.sizeToSectors(1, "MiB", device.sectorSize) #print "start %s" % start end = device.getLength() - start - 1024 #print end # Alignment #cylinder = device.endSectorToCylinder(end) #end = device.endCylinderToSector(cylinder) #print end try: geometry = parted.Geometry(device=device, start=start, end=end) except: print "Geometry error - Can't create partition" sys.exit(5) # fstype fs = parted.FileSystem(type=fstype, geometry=geometry) # Create partition partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=geometry, fs=fs) constraint = parted.Constraint(exactGeom=geometry) disk.addPartition(partition=partition, constraint=constraint) disk.commit() # Format partition according to the fstype specified if fstype == "fat32": os.system("mkdosfs -F 32 -n \"%s\" %s >/dev/null 2>&1" % (volume_label, partition.path)) if fstype == "ntfs": os.system("mkntfs -f -L \"%s\" %s >/dev/null 2>&1" % (volume_label, partition.path)) elif fstype == "ext4": os.system("mkfs.ext4 -L \"%s\" %s >/dev/null 2>&1" % (volume_label, partition.path)) sys.exit(0)
def __make_root__(device, start=config["ROOT"]["START"], end=config["ROOT"]["END"], fs=config["ROOT"]["fs"]): """Make root partition""" # __parted__(device, ["mkpart", name, fs, str(start), str(end)]) size = sectors_to_size(device.length, device.sectorSize) try: if start[-1] == "%": start = int(start[:-1]) / 100 start = int(size * start) except TypeError: pass try: if end[-1] == "%": end = int(end[:-1]) / 100 end = int(size * end) except TypeError: pass disk = parted.Disk(device) start_geo = parted.geometry.Geometry(device=device, start=parted.sizeToSectors(common.real_number(start - 20), "MB", device.sectorSize), end=parted.sizeToSectors(start + 20, "MB", device.sectorSize)) end_geo = parted.geometry.Geometry(device=device, start=parted.sizeToSectors(common.real_number(end - 40), "MB", device.sectorSize), end=parted.sizeToSectors(end, "MB", device.sectorSize)) min_size = parted.sizeToSectors(common.real_number((end - start) - 150), "MB", device.sectorSize) max_size = parted.sizeToSectors(common.real_number((end - start) + 150), "MB", device.sectorSize) const = parted.Constraint(startAlign=device.optimumAlignment, endAlign=device.optimumAlignment, startRange=start_geo, endRange=end_geo, minSize=min_size, maxSize=max_size) geometry = parted.geometry.Geometry(start=parted.sizeToSectors(start, "MB", device.sectorSize), length=parted.sizeToSectors((end - start), "MB", device.sectorSize), device=device) new_part = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=geometry) disk.addPartition(partition=new_part, constraint=const) disk.commit() time.sleep(0.1) __mkfs__(new_part.path, fs) return new_part.path
def premkpart(args, dev, disk): """Given args, device and disk needed to make parted. The format of args: args = [part.type, start, end, filesystem.type]. Raise Exception given wrong args.""" parttype = primary fstype = None if disk.type == 'msdos': parttype = args[0] del args[0] start = parted.sizeToSectors(int(args[0]), "MiB", 512) end = parted.sizeToSectors(int(args[1]), "MiB", 512) if not (parttype == "extended"): fstype = args[2] disk = rfparted.mkpart(dev, disk, parttype, start, end, fstype) return disk
def raw_format(device_path, fstype, volume_label, uid, gid): do_umount(device_path) # First erase MBR and partition table , if any os.system ("dd if=/dev/zero of=%s bs=512 count=1 >/dev/null 2>&1" % device_path) device = parted.getDevice(device_path) # Create a default partition set up disk = parted.freshDisk(device, 'msdos') try: disk.commit() except: # Unable to write the new partition print "Can't create partition. The device could be read-only." sys.exit(5) regions = disk.getFreeSpaceRegions() if len(regions) > 0: #print "Build partition" # Define size start = parted.sizeToSectors(1, "MiB", device.sectorSize) #print "start %s" % start end = device.getLength() - start - 1024 #print end # Alignment #cylinder = device.endSectorToCylinder(end) #end = device.endCylinderToSector(cylinder) #print end try: geometry = parted.Geometry(device=device, start=start, end=end) except: print "Geometry error - Can't create partition" sys.exit(5) # fstype fs = parted.FileSystem(type=fstype, geometry=geometry) # Create partition partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=geometry, fs=fs) constraint = parted.Constraint(exactGeom=geometry) disk.addPartition(partition=partition, constraint=constraint) disk.commit() # Format partition according to the fstype specified if fstype == "fat32": os.system("mkdosfs -F 32 -n \"%s\" %s >/dev/null 2>&1" % (volume_label, partition.path)) if fstype == "ntfs": os.system("mkntfs -f -L \"%s\" %s >/dev/null 2>&1" % (volume_label, partition.path)) elif fstype == "ext4": os.system("mkfs.ext4 -E root_owner=%s:%s -L \"%s\" %s >/dev/null 2>&1" % (uid, gid, volume_label, partition.path)) sys.exit(0)
def particion_pri(sdb, disk, size, tipo, fin): geometry1 = parted.Geometry(start=fin, length=parted.sizeToSectors( size, 'MiB', sdb.sectorSize), device=sdb) filesystem1 = parted.FileSystem(type=tipo, geometry=geometry1) partition1 = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=filesystem1, geometry=geometry1) disk.addPartition(partition1, constraint=sdb.optimalAlignedConstraint) disk.commit() return partition1.geometry.end
def bolumOlustur(self, alan, bolumTur): if bolumTur == parted.PARTITION_NORMAL or bolumTur == parted.PARTITION_EXTENDED: for bosBolum in self.disk.getFreeSpacePartitions(): _bolum = self.bolumBilgi(bosBolum, "GB") if _bolum["tur"] == parted.PARTITION_FREESPACE: maksBoyut = float(_bolum["boyut"]) elif bolumTur == bolumTur == parted.PARTITION_LOGICAL: for bosBolum in self.disk.getFreeSpacePartitions(): _bolum = self.bolumBilgi(bosBolum, "GB") if _bolum["tur"] == 5: maksBoyut = float(_bolum["boyut"]) alignment = self.aygit.optimalAlignedConstraint constraint = self.aygit.getConstraint() data = { 'start': constraint.startAlign.alignUp(alan, alan.start), 'end': constraint.endAlign.alignDown(alan, alan.end), } boyut, ok = QInputDialog().getDouble(self, 'Bölüm oluştur', 'GB cinsinden boyut:', min=0.001, value=1, max=maksBoyut, decimals=3) if ok: data["end"] = int(data["start"]) + int( parted.sizeToSectors(float(boyut), "GiB", self.aygit.sectorSize)) try: geometry = parted.Geometry(device=self.aygit, start=int(data["start"]), end=int(data["end"])) partition = parted.Partition( disk=self.disk, type=bolumTur, geometry=geometry, ) self.disk.addPartition(partition=partition, constraint=constraint) except (parted.PartitionException, parted.GeometryException, parted.CreateException) as e: # GeometryException accounts for incorrect start/end values (e.g. start < end), # CreateException is raised e.g. when the partition doesn't fit on the disk. # PartedException is a generic error (e.g. start/end values out of range) raise RuntimeError(e.message)
def _get_root_fs_size_in(self, sector_size): proc_comm = ProcessCommunicator() self.command_executor.Execute(command_to_execute="dumpe2fs -h /dev/sda1", raise_exception_on_failure=True, communicator=proc_comm) root_fs_block_count = re.findall(r'Block count:\s*(\d+)', proc_comm.stdout) root_fs_block_size = re.findall(r'Block size:\s*(\d+)', proc_comm.stdout) if not root_fs_block_count or not root_fs_block_size: raise Exception("Error parsing dumpe2fs output, count={0}, size={1}".format(root_fs_block_count, root_fs_block_size)) root_fs_block_count = int(root_fs_block_count[0]) root_fs_block_size = int(root_fs_block_size[0]) root_fs_size = parted.sizeToSectors(root_fs_block_count * root_fs_block_size, 'B', sector_size) return root_fs_size
def on_mkpart(self, devpath, parttype, start, size, end, fs): data = {} if self.has_disk(devpath): disk = self.disks[devpath] dev = parted.getDevice(devpath) partnumber = [ part.number for part in disk.partitions ] size = parted.sizeToSectors(size, "GB", 512) try: self.disks[devpath] = lib.rfparted.mkpart(dev, disk, parttype, start,size, end, fs) self.disks_tag[devpath] = True except Exception, e: data = self.error_handle(e,None) for p in disk.partitions: if p.number in partnumber: continue data = self.error_handle(None,"add"+devpath+ str(p.number)) break;
def _get_root_fs_size_in(self, sector_size): proc_comm = ProcessCommunicator() attempt = 1 while attempt < 10: dump_result = self.command_executor.Execute( command_to_execute="dumpe2fs -h {0}".format( self.rootfs_block_device), raise_exception_on_failure=False, communicator=proc_comm) if dump_result == 0: break self.command_executor.Execute('systemctl restart systemd-udevd') self.command_executor.Execute( 'systemctl restart systemd-timesyncd') self.command_executor.Execute('udevadm trigger') sleep(10) attempt += 1 if not attempt < 10: return Exception("Could not dumpe2fs, stderr: \n{0}".format( proc_comm.stderr)) root_fs_block_count = re.findall(r'Block count:\s*(\d+)', proc_comm.stdout) root_fs_block_size = re.findall(r'Block size:\s*(\d+)', proc_comm.stdout) if not root_fs_block_count or not root_fs_block_size: raise Exception( "Error parsing dumpe2fs output, count={0}, size={1}".format( root_fs_block_count, root_fs_block_size)) root_fs_block_count = int(root_fs_block_count[0]) root_fs_block_size = int(root_fs_block_size[0]) root_fs_size = parted.sizeToSectors( root_fs_block_count * root_fs_block_size, 'B', sector_size) return root_fs_size
def __make_efi__(device, start=config["EFI"]["START"], end=config["EFI"]["END"]): """Make EFI partition""" disk = parted.Disk(device) start_geo = parted.geometry.Geometry(device=device, start=parted.sizeToSectors(start, "MB", device.sectorSize), end=parted.sizeToSectors(start + 10, "MB", device.sectorSize)) end_geo = parted.geometry.Geometry(device=device, start=parted.sizeToSectors(common.real_number(end - 20), "MB", device.sectorSize), end=parted.sizeToSectors(end + 10, "MB", device.sectorSize)) min_size = parted.sizeToSectors(common.real_number((end - start) - 25), "MB", device.sectorSize) max_size = parted.sizeToSectors(common.real_number((end - start) + 20), "MB", device.sectorSize) const = parted.Constraint(startAlign=device.optimumAlignment, endAlign=device.optimumAlignment, startRange=start_geo, endRange=end_geo, minSize=min_size, maxSize=max_size) geometry = parted.geometry.Geometry(start=start, length=parted.sizeToSectors(end - start, "MB", device.sectorSize), device=device) new_part = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=geometry) new_part.setFlag(parted.PARTITION_BOOT) disk.addPartition(partition=new_part, constraint=const) disk.commit() time.sleep(0.1) __mkfs_fat__(new_part.path) return new_part.path
def _get_root_fs_size_in(self, sector_size): proc_comm = ProcessCommunicator() attempt = 1 while attempt < 10: dump_result = self.command_executor.Execute(command_to_execute="dumpe2fs -h {0}".format(self.rootfs_block_device), raise_exception_on_failure=False, communicator=proc_comm) if dump_result == 0: break self.command_executor.Execute('systemctl restart systemd-udevd') self.command_executor.Execute('systemctl restart systemd-timesyncd') self.command_executor.Execute('udevadm trigger') sleep(10) attempt += 1 if not attempt < 10: return Exception("Could not dumpe2fs, stderr: \n{0}".format(proc_comm.stderr)) root_fs_block_count = re.findall(r'Block count:\s*(\d+)', proc_comm.stdout) root_fs_block_size = re.findall(r'Block size:\s*(\d+)', proc_comm.stdout) if not root_fs_block_count or not root_fs_block_size: raise Exception("Error parsing dumpe2fs output, count={0}, size={1}".format(root_fs_block_count, root_fs_block_size)) root_fs_block_count = int(root_fs_block_count[0]) root_fs_block_size = int(root_fs_block_size[0]) root_fs_size = parted.sizeToSectors(root_fs_block_count * root_fs_block_size, 'B', sector_size) return root_fs_size
def enter(self): if not self.should_enter(): return self.context.logger.log("Entering split_root_partition state") device = parted.getDevice('/dev/sda') disk = parted.newDisk(device) original_root_fs_size = self._get_root_fs_size_in(device.sectorSize) self.context.logger.log("Original root filesystem size (sectors): {0}".format(original_root_fs_size)) desired_boot_partition_size = parted.sizeToSectors(256, 'MiB', device.sectorSize) self.context.logger.log("Desired boot partition size (sectors): {0}".format(desired_boot_partition_size)) desired_root_fs_size = original_root_fs_size - desired_boot_partition_size self.context.logger.log("Desired root filesystem size (sectors): {0}".format(desired_root_fs_size)) self.command_executor.Execute("resize2fs /dev/sda1 {0}s".format(desired_root_fs_size), True) resized_root_fs_size = self._get_root_fs_size_in(device.sectorSize) self.context.logger.log("Resized root filesystem size (sectors): {0}".format(resized_root_fs_size)) if not desired_root_fs_size == resized_root_fs_size: raise Exception("resize2fs failed, desired: {0}, resized: {1}".format(desired_root_fs_size, resized_root_fs_size)) self.context.logger.log("Root filesystem resized successfully") root_partition = disk.partitions[0] original_root_partition_start = root_partition.geometry.start original_root_partition_end = root_partition.geometry.end self.context.logger.log("Original root partition start (sectors): {0}".format(original_root_partition_start)) self.context.logger.log("Original root partition end (sectors): {0}".format(original_root_partition_end)) desired_root_partition_start = original_root_partition_start desired_root_partition_end = original_root_partition_end - desired_boot_partition_size desired_root_partition_size = desired_root_partition_end - desired_root_partition_start self.context.logger.log("Desired root partition start (sectors): {0}".format(desired_root_partition_start)) self.context.logger.log("Desired root partition end (sectors): {0}".format(desired_root_partition_end)) self.context.logger.log("Desired root partition size (sectors): {0}".format(desired_root_partition_size)) desired_root_partition_geometry = parted.Geometry(device=device, start=desired_root_partition_start, length=desired_root_partition_size) root_partition_constraint = parted.Constraint(exactGeom=desired_root_partition_geometry) disk.setPartitionGeometry(partition=root_partition, constraint=root_partition_constraint, start=desired_root_partition_start, end=desired_root_partition_end) desired_boot_partition_start = disk.getFreeSpaceRegions()[1].start desired_boot_partition_end = disk.getFreeSpaceRegions()[1].end desired_boot_partition_size = disk.getFreeSpaceRegions()[1].length self.context.logger.log("Desired boot partition start (sectors): {0}".format(desired_boot_partition_start)) self.context.logger.log("Desired boot partition end (sectors): {0}".format(desired_boot_partition_end)) desired_boot_partition_geometry = parted.Geometry(device=device, start=desired_boot_partition_start, length=desired_boot_partition_size) boot_partition_constraint = parted.Constraint(exactGeom=desired_boot_partition_geometry) desired_boot_partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=desired_boot_partition_geometry) disk.addPartition(partition=desired_boot_partition, constraint=boot_partition_constraint) disk.commit() probed_root_fs = parted.probeFileSystem(disk.partitions[0].geometry) if not probed_root_fs == 'ext4': raise Exception("Probed root fs is not ext4") disk.partitions[1].setFlag(parted.PARTITION_BOOT) disk.commit() self.command_executor.Execute("partprobe", True) self.command_executor.Execute("mkfs.ext2 /dev/sda2", True) boot_partition_uuid = self._get_uuid("/dev/sda2") # Move stuff from /oldroot/boot to new partition, make new partition mountable at the same spot self.command_executor.Execute("mount /dev/sda1 /oldroot", True) self.command_executor.Execute("mkdir /oldroot/memroot", True) self.command_executor.Execute("mount --make-rprivate /", True) self.command_executor.Execute("pivot_root /oldroot /oldroot/memroot", True) self.command_executor.ExecuteInBash("for i in dev proc sys; do mount --move /memroot/$i /$i; done", True) self.command_executor.Execute("mv /boot /boot.backup", True) self.command_executor.Execute("mkdir /boot", True) self._append_boot_partition_uuid_to_fstab(boot_partition_uuid) self.command_executor.Execute("cp /etc/fstab /memroot/etc/fstab", True) self.command_executor.Execute("mount /boot", True) self.command_executor.ExecuteInBash("mv /boot.backup/* /boot/", True) self.command_executor.Execute("rmdir /boot.backup", True) self.command_executor.Execute("mount --make-rprivate /", True) self.command_executor.Execute("pivot_root /memroot /memroot/oldroot", True) self.command_executor.Execute("rmdir /oldroot/memroot", True) self.command_executor.ExecuteInBash("for i in dev proc sys; do mount --move /oldroot/$i /$i; done", True) self.command_executor.Execute("systemctl restart rsyslog", True) self.command_executor.Execute("systemctl restart systemd-udevd", True) self.command_executor.Execute("systemctl restart walinuxagent", True) self.command_executor.Execute("umount /oldroot/boot", True) self.command_executor.Execute("umount /oldroot", True)
def apply_disk_strategy(self, simulate): """ Attempt to apply the given disk strategy """ strategy = self.info.strategy ops = strategy.get_operations() table_ops = [x for x in ops if isinstance(x, DiskOpCreateDisk)] resizes = [x for x in ops if isinstance(x, DiskOpResizeOS)] if len(table_ops) > 1: self.set_error_message("Wiping disk more than once, error") return False if len(resizes) > 1: self.set_error_message("Multiple resizes not supported") return False # Madman time: Go apply the operations. *Gulp* disk = strategy.disk if disk and simulate: disk = disk.duplicate() part_offset = 0 part_step = parted.sizeToSectors(16, 'kB', strategy.device.sectorSize) if disk: # Start at the very beginning of the disk, we don't # support free-space installation part_offset = disk.getFirstPartition().geometry.end + part_step for op in ops: self.set_display_string(op.describe()) op.set_part_offset(part_offset) if not op.apply(disk, simulate): er = op.get_errors() if not er: er = "Failed to apply operation: {}".format(op.describe()) self.set_error_message(er) return False # If it created a disk, go use it. if isinstance(op, DiskOpCreateDisk): disk = op.disk if not strategy.disk: strategy.disk = disk # Now set the part offset part_offset = disk.getFirstPartition().geometry.end + part_step elif isinstance(op, DiskOpResizeOS): part_offset = op.new_part_off + part_step elif isinstance(op, DiskOpCreatePartition): # Push forward the offset part_offset = op.part_end + part_step if simulate: return True try: disk.commit() except Exception as e: self.set_error_message("Failed to update disk: {}".format(e)) return False try: os.system("sync") except: pass # Post-process, format all the things for op in ops: if not isinstance(op, DiskOpCreatePartition): continue # Wait for device to show up! if not self.wait_disk(op): return False if not op.apply_format(disk): e = op.get_errors() self.set_error_message("Failed to apply format: {}".format(e)) return False return True
def create_partitions(self): """This method creates the partition table and the different partitions in the loopback device. It first read the device definition, then iterate the list of partitions. Device operation are done using the pyparted library. """ #TODO cleanup method to remove loopback # Output current task to logs logging.info( "Creating the partitions in the image mounted in loopback") # Retrieve the partition type to create if Key.LABEL.value not in self.project.image[Key.DEVICES.value]: self.project.logging.warning( "Partition table label is not defined, defaulting to dos.") label = "msdos" else: label = self.project.image[Key.DEVICES.value][Key.LABEL.value] # Check that the value is in the list of valid values if label not in "aix" "amiga" "bsd" "dvh" "gpt" "loop" "mac" "msdos" "pc98" "sun": self.project.logging.critical("Unknown partition label '" + label + "' . Aborting") exit(1) else: self.project.logging.debug("Using partition label '" + label + "'") # Retrieve the partition alignment if Key.ALIGNMENT.value not in self.project.image[Key.DEVICES.value]: self.project.logging.warning( "Partition alignment is not defined, defaulting to none.") alignment = "none" else: alignment = self.project.image[Key.DEVICES.value][ Key.ALIGNMENT.value] # TODO : handle partition alignment # Check that the value is in the list of valid values # if alignment == "none": # parted_alignment = None # elif alignment == "optimal": # parted_alignment = parted.OPTIMAL # elif alignment == "cylinder": # parted_alignment = cylinder # elif alignment == "minimal": # parted_alignment = minimal # else: # self.project.logging.critical("Unknown partition alignment '" + alignment + "' . Aborting") # exit(1) self.project.logging.debug("Using partition alignment '" + alignment + "'") # Create the partition tabl on the device device = parted.getDevice(self.loopback_device) # Create a new disk object disk = parted.freshDisk(device, label) # Check that there is a partition table inthe configuration file. If not it will fail later, # thus better fail now. if Key.PARTITIONS.value not in self.project.image[Key.DEVICES.value]: self.project.logging.error( "Partition table is not defined, nothing to do. Aborting") exit(1) # Nox iterate the partitiontables and create them for partition in self.project.image[Key.DEVICES.value][ Key.PARTITIONS.value]: # Retrieve the partition name if Key.NAME.value in partition: part_name = partition[Key.NAME.value] else: part_name = "" self.project.logging.debug("Partition name => '" + part_name + "'") # Retrieve the partition type if Key.TYPE.value in partition: part_type = partition[Key.TYPE.value] else: part_type = "primary" # Check that the partition type is valid and convert in parted "define" if part_type == "primary": parted_type = parted.PARTITION_NORMAL elif part_type == "extended": parted_type = parted.PARTITION_EXTENDED elif part_type == "logical": parted_type = parted.PARTITION_LOGICAL else: self.project.logging.critical("Unknown partition type '" + part_type + "' . Aborting") exit(1) self.project.logging.debug("Partition type => '" + part_type + "'") # Retrieve the partition size if Key.SIZE.value not in partition: self.project.logging.critical( "Partition size is not defined. Aborting") exit(1) else: # Retrieve the value and control it is an integer try: part_size = int(partition[Key.SIZE.value]) except ValueError: self.project.logging.critical( "Partition size is not a number : " + partition[Key.SIZE.value]) exit(1) self.project.logging.debug("Partition size => '" + str(part_size) + "'") # Retrieve the partition unit if Key.UNIT.value not in partition: self.project.logging.warning( "Partition size unit is not defined, defaultig to MB.") part_unit = "MB" else: part_unit = partition[Key.UNIT.value] # Compute the block size to use based on the unit if part_unit not in "s" "B" "KB" "KiB" "MB" "MiB" "GB" "GiB" "TB" "TiB": self.project.logging.critical("Unknwon unit '" + part_unit + "' . Aborting") exit(1) else: self.project.logging.debug("Partition unit => '" + part_unit + "'") # Retrieve the partition start sector if Key.START_SECTOR.value not in partition: self.project.logging.warning( "Partition start_sector is not defined. " + "Using next available in sequence") part_start_sector = -1 else: # Retrieve the value and control it is an integer try: part_start_sector = int(partition[Key.START_SECTOR.value]) except ValueError: self.project.logging.critical( "Partition start_sector is not a number : " + partition[Key.START_SECTOR.value]) exit(1) self.project.logging.debug("Partition start sector => '" + str(part_start_sector) + "'") # Retrieve the partition flags if Key.FLAGS.value not in partition: self.project.logging.debug( "Partition flags are not defined. Skipping...") part_flags = None else: part_flags = partition[Key.FLAGS.value] self.project.logging.debug("Partition flags => '" + part_flags + "'") # Retrieve the partition file system type if Key.FILESYSTEM.value not in partition: self.project.logging.debug( "File system to create on the partition is not defined.") part_filesystem = None else: part_filesystem = partition[Key.FILESYSTEM.value].lower() # Check that the value is in the list of valid values if part_filesystem not in parted.fileSystemType: self.project.logging.critical("Unknown filesystem type '" + part_filesystem + "' . Aborting") exit(1) else: self.project.logging.debug("Filesystem type => '" + part_filesystem + "'") # Retrieve the partition format flag if Key.FORMAT.value not in partition: self.project.logging.debug( "File system format flag is not defined. Defaulting to True" ) part_format = True else: part_format = partition[Key.FORMAT.value] self.project.logging.debug("File system format flag => '" + str(part_format) + "'") # # All information have been parsed,now let's create the partition in the loopback device # # Compute the sector count based on size and unit. Need for parted sector_count = parted.sizeToSectors(part_size, part_unit, device.sectorSize) # Compute the geometry for this device geometry = parted.Geometry(start=part_start_sector, length=sector_count, device=device) # Create the arted filesystem object filesys = parted.FileSystem(type=part_filesystem, geometry=geometry) # Create the partition object in the loopback device new_partition = parted.Partition(disk=disk, type=parted_type, geometry=geometry, fs=filesys) # Create the constraint object for alignment, etc. # constraint = parted.Constraint(startAlign=parted_alignment, endAlign=parted_alignment, \ # startRange=start, endRange=end, minSize=min_size, maxSize=max_size) constraint = parted.Constraint(exactGeom=new_partition.geometry) # Add the partition to the disk disk.addPartition(partition=new_partition, constraint=constraint) # Make modification persistent to disk disk.commit()
def _kib_to_sectors(self, device, kib): return parted.sizeToSectors(kib, 'KiB', device.sectorSize)
def apply_disk_strategy(self, simulate): """ Attempt to apply the given disk strategy """ strategy = self.info.strategy ops = strategy.get_operations() table_ops = [x for x in ops if isinstance(x, DiskOpCreateDisk)] resizes = [x for x in ops if isinstance(x, DiskOpResizeOS)] if len(table_ops) > 1: self.set_error_message("Wiping disk more than once, error") return False if len(resizes) > 1: self.set_error_message("Multiple resizes not supported") return False # Madman time: Go apply the operations. *Gulp* disk = strategy.disk if disk and simulate: disk = disk.duplicate() part_offset = 0 part_step = parted.sizeToSectors(1, 'MiB', strategy.device.sectorSize) if disk: # Start at the very beginning of the disk, we don't # support free-space installation part_offset = self.round_up_next_block( disk.getFirstPartition().geometry.end, part_step) for op in ops: self.set_display_string(op.describe()) op.set_part_offset(part_offset) if not op.apply(disk, simulate): er = op.get_errors() if not er: er = "Failed to apply operation: {}".format(op.describe()) self.set_error_message(er) return False # If it created a disk, go use it. if isinstance(op, DiskOpCreateDisk): disk = op.disk if not strategy.disk: strategy.disk = disk # Now set the part offset part_offset = self.round_up_next_block( disk.getFirstPartition().geometry.end, part_step) elif isinstance(op, DiskOpResizeOS): part_offset = self.round_up_next_block(op.new_part_off, part_step) elif isinstance(op, DiskOpCreatePartition): # Push forward the offset part_offset = self.round_up_next_block(op.part_end, part_step) if simulate: return True try: disk.commit() except Exception as e: self.set_error_message("Failed to update disk: {}".format(e)) return False try: os.system("sync") except: pass # Post-process, format all the things post_types = [ DiskOpCreatePartition, DiskOpCreateLogicalVolume, DiskOpCreateVolumeGroup, DiskOpFormatRootLate, DiskOpFormatSwapLate, ] for op in ops: is_type = False for t in post_types: if isinstance(op, t): is_type = True break if not is_type: continue # Wait for device to show up! if isinstance(op, DiskOpCreatePartition): if not self.wait_disk(op): return False p = op.describe() self.set_display_string("Applying operation: {}".format(p)) if not op.apply_format(disk): e = op.get_errors() self.set_error_message("Failed to apply format: {}".format(e)) print(op.describe()) return False return True
def new(self): """Create a new partition from free space.""" def create_primary(): """Create a new primary partition.""" return parted.PARTITION_NORMAL def create_logical(): """Create a new logical partition.""" return parted.PARTITION_LOGICAL def cancel(): """Don't create a partition.""" self.vis_opts = self.free_opts self.draw_options() return None def at_beginning(): """Add partition at beginning of free space.""" return "Beginning" def at_end(): """Add partiton at end of free space.""" return "End" opts1 = (("Primary", create_primary), ("Logical", create_logical), ("Cancel", cancel)) opts2 = (("Beginning", at_beginning), ("End", at_end), ("Cancel", cancel)) alignment = self.device.optimumAlignment sector_size = self.device.sectorSize free = self.__partition.geometry start = free.start end = free.end length = None # Determine what type of partition to create. part_type = check_free_space(self.__partition) if part_type == "Pri/Log": part_type = self.sub_menu(opts1) if part_type is None: return elif part_type == "Primary": part_type = parted.PARTITION_NORMAL else: part_type = parted.PARTITION_LOGICAL # Determine what length the new partition should be. text = "Size in {:}: ".format(self.unit) offset = self.center(text + str(free.getLength(self.unit))) self.window.hline(self.menu_line, 0, " ", self.window_width) self.window.addstr(self.menu_line, offset, text + str(free.getLength(self.unit))) self.window.move(self.menu_line, offset + len(text)) key = self.window.getkey() if key != "\n": self.window.clrtoeol() editwin = curses.newwin(1, 20, self.menu_line, offset + len(text)) editwin.addstr(key) textbox = curses.textpad.Textbox(editwin) accept_bs = lambda key: curses.KEY_BACKSPACE if key == 127 else key try: length = float(textbox.edit(accept_bs)) if self.unit != "sectors": length = parted.sizeToSectors(length, self.unit, sector_size) else: length = int(length) except Exception as e: self.refresh_menu() self.draw_info("ERROR: {:}".format(e)) return # Determine whether the partition should be placed at the beginning or end # of the free space, and adjust the start/end locations accordingly. if length and length < free.length: location = self.sub_menu(opts2) if location == "Beginning": end = start + length elif location == "End": start = end - length else: return try: # Create or extend an extended partition to hold the logical one. if part_type == parted.PARTITION_LOGICAL: grow_ext(self.__partition) if not alignment.isAligned(free, start): start = alignment.alignDown(free, start) if not alignment.isAligned(free, end): end = alignment.alignUp(free, end) free = parted.Geometry(self.device, start, end = end) max_length = self.disk.maxPartitionLength if max_length and max_length < free.length: self.draw_info("ERROR: partition size too large") return part = parted.Partition(self.disk, part_type, geometry = free) constraint = parted.Constraint(exactGeom = free) self.disk.addPartition(part, constraint) except Exception as e: if part_type == parted.PARTITION_LOGICAL: self.disk.minimizeExtendedPartition() self.refresh_menu() self.draw_info("ERROR: {:}".format(e)) return if part_type == parted.PARTITION_LOGICAL: self.disk.minimizeExtendedPartition() self.refresh_menu()
def __make_root__(device, start=config["ROOT"]["START"], end=config["ROOT"]["END"], fs=config["ROOT"]["fs"]): """Make root partition""" # __parted__(device, ["mkpart", name, fs, str(start), str(end)]) size = sectors_to_size(device.length, device.sectorSize) try: if start[-1] == "%": start = int(start[:-1]) / 100 start = int(size * start) except TypeError: pass try: if end[-1] == "%": end = int(end[:-1]) / 100 end = int(size * end) except TypeError: pass disk = parted.Disk(device) s_geo = parted.geometry.Geometry( device=device, start=parted.sizeToSectors(common.real_number(start - 20), "MB", device.sectorSize), end=parted.sizeToSectors(start + 20, "MB", device.sectorSize)) e_geo = parted.geometry.Geometry( device=device, start=parted.sizeToSectors(common.real_number(end - 100), "MB", device.sectorSize), end=parted.sizeToSectors(end, "MB", device.sectorSize)) min_size = parted.sizeToSectors(common.real_number((end - start) - 250), "MB", device.sectorSize) max_size = parted.sizeToSectors(common.real_number((end - start) + 250), "MB", device.sectorSize) const = parted.Constraint(startAlign=device.optimumAlignment, endAlign=device.optimumAlignment, startRange=s_geo, endRange=e_geo, minSize=min_size, maxSize=max_size) geo = parted.geometry.Geometry(start=parted.sizeToSectors( start, "MB", device.sectorSize), length=parted.sizeToSectors( (end - start), "MB", device.sectorSize), device=device) new_part = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=geo) try: disk.addPartition(partition=new_part, constraint=const) except parted._ped.PartitionException: # Simply use the geometry of the first free space region, if it is big enough data = disk.getFreeSpaceRegions() sizes = {} for each in data: sizes[each.getSize(unit="b")] = each sizes_sorted = sorted(sizes) made = False for each in range(len(sizes_sorted) - 1, -1, -1): if sizes[sizes_sorted[each]].getSize( unit="b") >= get_min_root_size(): s_geo = parted.geometry.Geometry( device=device, start=parted.sizeToSectors( common.real_number(sizes[sizes_sorted[each]].start - 2000), "MB", device.sectorSize), end=parted.sizeToSectors( sizes[sizes_sorted[each]].start + 2000, "MB", device.sectorSize)) e_geo = parted.geometry.Geometry( device=device, start=parted.sizeToSectors( common.real_number(sizes[sizes_sorted[each]].end - 2000), "MB", device.sectorSize), end=parted.sizeToSectors( sizes[sizes_sorted[each]].end + 2000, "MB", device.sectorSize)) min_size = parted.sizeToSectors( common.real_number((sizes[sizes_sorted[each]].end - sizes[sizes_sorted[each]].start) - 2000), "MB", device.sectorSize) max_size = parted.sizeToSectors( common.real_number((sizes[sizes_sorted[each]].end - sizes[sizes_sorted[each]].start) + 2000), "MB", device.sectorSize) const = parted.Constraint(startAlign=device.optimumAlignment, endAlign=device.optimumAlignment, startRange=s_geo, endRange=e_geo, minSize=min_size, maxSize=max_size) new_part = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=sizes[sizes_sorted[each]]) try: disk.addPartition(partition=new_part, constraint=const) except: break made = True break if not made: common.eprint( "WAS NOT ABLE TO CREATE ROOT PARTITION. LIKELY NOT ENOUGH SPACE FOR ONE." ) common.eprint("INSTALLATION WILL FAIL") disk.commit() time.sleep(0.1) __mkfs__(new_part.path, fs) return new_part.path
def partition(root, efi, home): """Partition drive 'root' for Linux installation root: needs to be path to installation drive (i.e.: /dev/sda, /dev/nvme0n1) efi: booleen indicated whether system was booted with UEFI home: whether to make a home partition, or if one already exists Possible values: None, 'NULL': Do not make a home partition, and one does not already exist 'MAKE': Make a home partition on the installation drive (some partition path): path to a partition to be used as home directory """ common.eprint("\t###\tauto_partioner.py STARTED\t###\t") part1 = None part2 = None part3 = None device = parted.getDevice(root) try: disk = parted.Disk(device) except parted._ped.DiskLabelException: common.eprint("NO PARTITION TABLE EXISTS. MAKING NEW ONE . . .") disk = parted.freshDisk(device, "gpt") size = sectors_to_size(device.length, device.sectorSize) * 1000 if home in ("NULL", "null", None, "MAKE"): common.eprint("DELETING PARTITIONS.") device.clobber() disk = parted.freshDisk(device, "gpt") disk.commit() else: common.eprint("HOME PARTITION EXISTS. NOT DELETING PARTITIONS.") if size == LIMITER: if efi: part1 = __make_efi__(device) part2 = __make_root__(device, end="100%") else: part1 = __make_root__(device, start="0%", end="100%") __make_root_boot__(device) common.eprint("\t###\tauto_partioner.py CLOSED\t###\t") return __generate_return_data__(home, efi, part1, part2, part3) # Handled 16GB drives # From here until 64GB drives, we want our root partition to be AT LEAST # 16GB if home == "MAKE": # If home == "MAKE", we KNOW there are no partitons because we made a # new partition table if size >= gb_to_bytes(config["mdswh"]): root_end = int((size * 0.35) / (1000 ** 2)) else: root_end = config["min root size"] if (efi and (part1 is None)): part1 = __make_efi__(device) part2 = __make_root__(device, end=root_end) part3 = __make_home__(device, new_start=root_end) elif part1 is None: part1 = __make_root__(device, start="0%", end=root_end) __make_root_boot__(device) part2 = __make_home__(device, new_start=root_end) common.eprint("\t###\tauto_partioner.py CLOSED\t###\t") return __generate_return_data__(home, efi, part1, part2, part3) if home in ("NULL", "null", None): # If home == any possible 'null' value, # we KNOW there are no partitons because we made a # new partition table if efi: part1 = __make_efi__(device) part2 = __make_root__(device, end="100%") else: part1 = __make_root__(device, start="0%", end="100%") __make_root_boot__(device) common.eprint("\t###\tauto_partioner.py CLOSED\t###\t") return __generate_return_data__(home, efi, part1, part2, part3) # This one we need to figure out if the home partiton is on the drive # we are working on or elsewhere if "nvme" in home: check = home[:-2] else: check = home[:-1] if root == check: # It IS on the same drive. We need to figure out where at and work # around it # NOTE: WE NEED TO WORK IN MB ONLY IN THIS SECTION disk = parted.Disk(device) data = disk.getFreeSpaceRegions() sizes = {} for each in data: sizes[each.length] = each sizes_sorted = sorted(sizes) # Lets make some partitons! if efi: for each in sizes_sorted: if sizes[each].getSize() >= 200: end = sizes[each].start + parted.sizeToSectors(200, "MB", device.sectorSize) end = sectors_to_size(end, device.sectorSize) part1 = __make_efi__(device, start=sizes[each].start, end=end) part2 = __make_root__(device, start=end, end=sizes[each].end) break else: for each in sizes_sorted: if sizes[each].getSize() >= 200: part1 = __make_root__(device, start=sizes[each].start, end=sizes[each].end) __make_root_boot__(device) break common.eprint("\t###\tauto_partioner.py CLOSED\t###\t") return __generate_return_data__(home, efi, part1, part2, part3) else: # it's elsewhere. We're good. if efi: part1 = __make_efi__(device) part2 = __make_root__(device) else: part1 = __make_root__(device, start="0%", end="100%") __make_root_boot__(device) part3 = home # Figure out what parts are for what # Return that data as a dictonary common.eprint("\t###\tauto_partioner.py CLOSED\t###\t") return __generate_return_data__(home, efi, part1, part2, part3)
def enter(self): if not self.should_enter(): return self.context.logger.log("Entering split_root_partition state") device = parted.getDevice(self.rootfs_disk) disk = parted.Disk(device) original_root_fs_size = self._get_root_fs_size_in(device.sectorSize) self.context.logger.log("Original root filesystem size (sectors): {0}".format(original_root_fs_size)) desired_boot_partition_size = parted.sizeToSectors(256, 'MiB', device.sectorSize) self.context.logger.log("Desired boot partition size (sectors): {0}".format(desired_boot_partition_size)) root_partition = disk.partitions[0] original_root_partition_start = root_partition.geometry.start original_root_partition_end = root_partition.geometry.end self.context.logger.log("Original root partition start (sectors): {0}".format(original_root_partition_start)) self.context.logger.log("Original root partition end (sectors): {0}".format(original_root_partition_end)) desired_root_partition_start = original_root_partition_start desired_root_partition_end = original_root_partition_end - desired_boot_partition_size desired_root_partition_size = desired_root_partition_end - desired_root_partition_start self.context.logger.log("Desired root partition start (sectors): {0}".format(desired_root_partition_start)) self.context.logger.log("Desired root partition end (sectors): {0}".format(desired_root_partition_end)) self.context.logger.log("Desired root partition size (sectors): {0}".format(desired_root_partition_size)) self.context.logger.log("Resizing root filesystem") desired_root_fs_size = desired_root_partition_size self._resize_root_fs_to_sectors(desired_root_fs_size, device.sectorSize) desired_root_partition_geometry = parted.Geometry(device=device, start=desired_root_partition_start, length=desired_root_partition_size) root_partition_constraint = parted.Constraint(exactGeom=desired_root_partition_geometry) disk.setPartitionGeometry(partition=root_partition, constraint=root_partition_constraint, start=desired_root_partition_start, end=desired_root_partition_end) desired_boot_partition_start = disk.getFreeSpaceRegions()[1].start desired_boot_partition_end = disk.getFreeSpaceRegions()[1].end desired_boot_partition_size = disk.getFreeSpaceRegions()[1].length self.context.logger.log("Desired boot partition start (sectors): {0}".format(desired_boot_partition_start)) self.context.logger.log("Desired boot partition end (sectors): {0}".format(desired_boot_partition_end)) desired_boot_partition_geometry = parted.Geometry(device=device, start=desired_boot_partition_start, length=desired_boot_partition_size) boot_partition_constraint = parted.Constraint(exactGeom=desired_boot_partition_geometry) desired_boot_partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=desired_boot_partition_geometry) disk.addPartition(partition=desired_boot_partition, constraint=boot_partition_constraint) disk.commit() probed_root_fs = parted.probeFileSystem(disk.partitions[0].geometry) if not probed_root_fs == 'ext4': raise Exception("Probed root fs is not ext4") disk.partitions[1].setFlag(parted.PARTITION_BOOT) disk.commit() self.command_executor.Execute("partprobe", False) self.command_executor.Execute("mkfs.ext2 {0}".format(self.bootfs_block_device), True) boot_partition_uuid = self._get_uuid(self.bootfs_block_device) # Move stuff from /oldroot/boot to new partition, make new partition mountable at the same spot self.command_executor.Execute("mount {0} /oldroot".format(self.rootfs_block_device), True) self.command_executor.Execute("mkdir /oldroot/memroot", True) self.command_executor.Execute("mount --make-rprivate /", True) self.command_executor.Execute("pivot_root /oldroot /oldroot/memroot", True) self.command_executor.ExecuteInBash("for i in dev proc sys; do mount --move /memroot/$i /$i; done", True) self.command_executor.Execute("mv /boot /boot.backup", True) self.command_executor.Execute("mkdir /boot", True) self._append_boot_partition_uuid_to_fstab(boot_partition_uuid) self.command_executor.Execute("cp /etc/fstab /memroot/etc/fstab", True) self.command_executor.Execute("mount /boot", True) self.command_executor.ExecuteInBash("mv /boot.backup/* /boot/", True) self.command_executor.Execute("rmdir /boot.backup", True) self.command_executor.Execute("mount --make-rprivate /", True) self.command_executor.Execute("pivot_root /memroot /memroot/oldroot", True) self.command_executor.Execute("rmdir /oldroot/memroot", True) self.command_executor.ExecuteInBash("for i in dev proc sys; do mount --move /oldroot/$i /$i; done", True) self.command_executor.Execute("service rsyslog restart", True) self.command_executor.Execute("service udev restart", True) self.command_executor.Execute("umount /oldroot/boot", True) try: self.command_executor.Execute("umount /oldroot", True) except: self.context.logger.log("Could not unmount /oldroot, attempting to restart WALA and unmount again") self.should_exit() self.context.logger.log("Removing marker for UnmountOldrootState") os.unlink(os.path.join(self.context.encryption_environment.os_encryption_markers_path, 'UnmountOldrootState')) self.command_executor.Execute('at -f /restart-wala.sh now + 1 minutes', True) self.command_executor.Execute('service walinuxagent stop', True)
def fdhandler(dev, mem, disks, sysflag): DevEndSector = dev.getLength() ##the last sector of the device Dsize = dev.getLength("GB") parttype = "primary" fs = "ext4" number = 0 ##record the number of the part created boot_number = 0 ##record the number of boot part disk = disks[dev.path] disk.deleteAllPartitions() disks[dev.path] = disk start = parted.sizeToSectors(0, "GB", 512) end = 0 if disk.type == "gpt": number = number + 1 size = parted.sizeToSectors(1, "MB", 512) disk = rfparted.mkpart(dev, disk, parttype, start, size, end, "bios_grub") start = start + size + 1 if sysflag == "sony": number = number + 1 fs = "ext3" size = parted.sizeToSectors(10, "GB", 512) disk = rfparted.mkpart(dev, disk, parttype, start, size, end, fs) start = start + size + 1 if Dsize > 54: number = number + 1 boot_number = number size = parted.sizeToSectors(50, "GB", 512) disk = rfparted.mkpart(dev, disk, parttype, start, size, end, fs) rfparted.setFlag(disk, number, "boot", True) start = start + size + 1 number = number + 1 size = parted.sizeToSectors(4, "GB", 512) disk = rfparted.mkpart(dev, disk, parttype, start, size, end, "linux-swap(v1)") elif Dsize > 10: if find_swap(disks) is False: number = number + 1 size = parted.sizeToSectors(mem, "B", 512) disk = rfparted.mkpart(dev, disk, parttype, start, size, end, "linux-swap(v1)") start = start + size + 1 if Dsize > 30: number = number + 1 boot_number = number end = parted.sizeToSectors(30, "GB", 512) ##rootsize = 30 - swap disk = rfparted.mkpart(dev, disk, parttype, start, 0, end, fs) start = end + 1 number = number + 1 if boot_number == 0: boot_number = number end = DevEndSector disk = rfparted.mkpart(dev, disk, parttype, start, 0, end, fs) elif Dsize >= 6: number = number + 1 boot_number = number end = DevEndSector disk = rfparted.mkpart(dev, disk, parttype, start, 0, end, fs) else: raise Exception, "Error, select a disk of at least 6 GB ." return [disk, boot_number]
def enter(self): if not self.should_enter(): return self.context.logger.log("Entering split_root_partition state") device = parted.getDevice(self.rootfs_disk) disk = parted.Disk(device) original_root_fs_size = self._get_root_fs_size_in(device.sectorSize) self.context.logger.log( "Original root filesystem size (sectors): {0}".format( original_root_fs_size)) desired_boot_partition_size = parted.sizeToSectors( 256, 'MiB', device.sectorSize) self.context.logger.log( "Desired boot partition size (sectors): {0}".format( desired_boot_partition_size)) root_partition = disk.partitions[0] original_root_partition_start = root_partition.geometry.start original_root_partition_end = root_partition.geometry.end self.context.logger.log( "Original root partition start (sectors): {0}".format( original_root_partition_start)) self.context.logger.log( "Original root partition end (sectors): {0}".format( original_root_partition_end)) desired_root_partition_start = original_root_partition_start desired_root_partition_end = original_root_partition_end - desired_boot_partition_size desired_root_partition_size = desired_root_partition_end - desired_root_partition_start self.context.logger.log( "Desired root partition start (sectors): {0}".format( desired_root_partition_start)) self.context.logger.log( "Desired root partition end (sectors): {0}".format( desired_root_partition_end)) self.context.logger.log( "Desired root partition size (sectors): {0}".format( desired_root_partition_size)) self.context.logger.log("Resizing root filesystem") desired_root_fs_size = desired_root_partition_size self._resize_root_fs_to_sectors(desired_root_fs_size, device.sectorSize) desired_root_partition_geometry = parted.Geometry( device=device, start=desired_root_partition_start, length=desired_root_partition_size) root_partition_constraint = parted.Constraint( exactGeom=desired_root_partition_geometry) disk.setPartitionGeometry(partition=root_partition, constraint=root_partition_constraint, start=desired_root_partition_start, end=desired_root_partition_end) desired_boot_partition_start = disk.getFreeSpaceRegions()[1].start desired_boot_partition_end = disk.getFreeSpaceRegions()[1].end desired_boot_partition_size = disk.getFreeSpaceRegions()[1].length self.context.logger.log( "Desired boot partition start (sectors): {0}".format( desired_boot_partition_start)) self.context.logger.log( "Desired boot partition end (sectors): {0}".format( desired_boot_partition_end)) desired_boot_partition_geometry = parted.Geometry( device=device, start=desired_boot_partition_start, length=desired_boot_partition_size) boot_partition_constraint = parted.Constraint( exactGeom=desired_boot_partition_geometry) desired_boot_partition = parted.Partition( disk=disk, type=parted.PARTITION_NORMAL, geometry=desired_boot_partition_geometry) disk.addPartition(partition=desired_boot_partition, constraint=boot_partition_constraint) disk.commit() probed_root_fs = parted.probeFileSystem(disk.partitions[0].geometry) if not probed_root_fs == 'ext4': raise Exception("Probed root fs is not ext4") disk.partitions[1].setFlag(parted.PARTITION_BOOT) disk.commit() self.command_executor.Execute("partprobe", False) self.command_executor.Execute( "mkfs.ext2 {0}".format(self.bootfs_block_device), True) boot_partition_uuid = self._get_uuid(self.bootfs_block_device) # Move stuff from /oldroot/boot to new partition, make new partition mountable at the same spot self.command_executor.Execute( "mount {0} /oldroot".format(self.rootfs_block_device), True) self.command_executor.Execute("mkdir -p /boot", True) self.command_executor.Execute("cp /oldroot/etc/fstab /etc/fstab", True) self._append_boot_partition_uuid_to_fstab(boot_partition_uuid) self.command_executor.Execute("cp /etc/fstab /oldroot/etc/fstab", True) self.command_executor.Execute("mount /boot", True) self.command_executor.ExecuteInBash("mv /oldroot/boot/* /boot/", True) self.command_executor.Execute("umount /boot", True) self.command_executor.Execute("umount /oldroot", True)
def editPartition(self, targetPartition, deltaStart, deltaEnd, fstype, fslabel, unit='MiB', formatPartition=True, safeDataThroughTmp=False): log.info("editPartition: Editing partition " + targetPartition.path + ". Start = Start + (" + str(deltaStart) + "). End = End + (" + str(deltaEnd) + ").") # Backup data to a directory in tmp if safeDataThroughTmp: # Make sure targetPartition is mounted in mountpoint if isMounted(targetPartition.path): mountpoint = getMountpoint(targetPartition.path) else: try: mountpoint = tempfile.mkdtemp(prefix='resinhup-', dir='/tmp') except: log.error("editPartition: Failed to create temporary mountpoint.") return False if not mount(targetPartition.path, mountpoint): log.error("editPartition: Failed to mount %s in %s." %(targetPartition.path, mountpoint)) return False # Backup files to a directory in /tmp try: backupdir = tempfile.mkdtemp(prefix='resinhup-', dir='/tmp') except: log.error("editPartition: Failed to create temporary backup directory.") return False if not safeCopy(mountpoint, backupdir): log.error("editPartition: Could not backup files from %s to %s." %(mountpoint, backupdir)) # Make sure that partition is not mounted if isMounted(targetPartition.path): if not umount(targetPartition.path): return False # Committing partition changes to OS needs udev running startUdevDaemon() # Calculate the new geometry geometry = targetPartition.geometry geometry.start += parted.sizeToSectors(deltaStart, unit, self.device.sectorSize) geometry.end += parted.sizeToSectors(deltaEnd, unit, self.device.sectorSize) # Destroy the partition and recreate it with the new geometry self.disk.deletePartition(targetPartition) filesystem = parted.FileSystem(type=fstype, geometry=geometry) partition = parted.Partition(disk=self.disk, type=parted.PARTITION_NORMAL, fs=filesystem, geometry=geometry) self.disk.addPartition(partition=partition, constraint=self.device.optimalAlignedConstraint) self.disk.commit() # Format filesystem if formatPartition: if (fstype == 'ext3') or (fstype == 'ext4'): if not formatEXT3(partition.path, fslabel): log.error("movePartition: Could not format " + partition.path + " as ext3.") return False elif fstype == 'fat32': if not formatVFAT(partition.path, fslabel): log.error("movePartition: Could not format " + partition.path + " as vfat.") return False else: log.error("movePartition: Format of " + fstype + " is not implemented.") return False # Restore data in targetPartition if safeDataThroughTmp: # Make sure targetPartition is mounted in mountpoint if isMounted(targetPartition.path): log.error("editPartition: Something is wrong. %s should not be mounted." % targetPartition.path) return False else: if not mount(targetPartition.path, mountpoint): log.error("editPartition: Failed to mount %s in %s." %(targetPartition.path, mountpoint)) return False # Copy back the data if not safeCopy(backupdir, mountpoint, sync=True): log.error("editPartition: Could not restore files from %s to %s." %(backupdir, mountpoint)) # Cleanup temporary backup files shutil.rmtree(backupdir) return True
def runTest(self): self.assertRaises(SyntaxError, parted.sizeToSectors, 9, "yb", 1) self.assertEqual(int(parted.sizeToSectors(7777.0, "B", 512)), parted.sizeToSectors(7777.0, "B", 512))
def partition(root, efi, home, raid_array): """Partition drive 'root' for Linux installation root: needs to be path to installation drive (i.e.: /dev/sda, /dev/nvme0n1) efi: booleen indicated whether system was booted with UEFI home: whether to make a home partition, or if one already exists Possible values: None, 'NULL': Do not make a home partition, and one does not exist 'MAKE': Make a home partition on the installation drive (some partition path): path to a partition to be used as home directory """ # Initial set up for partitioning common.eprint("\t###\tauto_partioner.py STARTED\t###\t") part1 = None part2 = None part3 = None if raid_array["raid_type"] not in (None, "OEM"): if raid_array["raid_type"].lower() == "raid0": raid_array["raid_type"] = 0 elif raid_array["raid_type"].lower() == "raid1": raid_array["raid_type"] = 1 elif raid_array["raid_type"].lower() == "raid10": raid_array["raid_type"] = 10 for each in raid_array["disks"]: if each in ("1", "2"): if raid_array["disks"][each] is None: # Invalid RAID array. Do not create. raid_array["raid_type"] = None # We double check this to ensure we are working with valid RAID arrays if raid_array["raid_type"] is not None: disks = [] for each in raid_array["disks"]: if raid_array["disks"][each] is not None: disks.append(raid_array["disks"][each]) raid_array["disks"] = disks device = parted.getDevice(root) try: disk = parted.Disk(device) except parted._ped.DiskLabelException: common.eprint("NO PARTITION TABLE EXISTS. MAKING NEW ONE . . .") disk = parted.freshDisk(device, "gpt") # sectors_to_size() returns size in MBs, multiply by 1 million to convert to bytes size = sectors_to_size(device.length, device.sectorSize) * 1000000 if ((home in ("NULL", "null", None, "MAKE")) and (raid_array["raid_type"] is None)): disk = clobber_disk(device) elif raid_array["raid_type"] is not None: disk = clobber_disk(device) common.eprint("CREATING RAID ARRAY") common.eprint(f"RAID TYPE: {raid_array['raid_type']}") if not make_raid_array(raid_array["disks"], raid_array["raid_type"]): common.eprint("INITIAL RAID ARRAY CREATION FAILED. FORCING . . .") if not make_raid_array( raid_array["disks"], raid_array["raid_type"], force=True): common.eprint("FORCED RAID ARRAY CREATION FAILED. BAD DRIVE?") common.eprint("FALLING BACK TO NO HOME PARTITION.") home = None else: # we know there is a pre-existing home partition # determine if it is on the same drive and act accordingly home_drive = get_drive_path(home) if home_drive == root: common.eprint("HOME PARTITION EXISTS. NOT DELETING PARTITIONS.") else: disk = clobber_disk(device) if size <= LIMITER: if efi: part1 = __make_efi__(device) part2 = __make_root__(device, end="100%") else: part1 = __make_root__(device, start="0%", end="100%") __make_root_boot__(device) common.eprint("\t###\tauto_partioner.py CLOSED\t###\t") return __generate_return_data__(home, efi, part1, part2, part3) # Handled 16GB drives # From here until 64GB drives, we want our root partition to be AT LEAST # 16GB if home == "MAKE": # If home == "MAKE", we KNOW there are no partitons because we made a # new partition table if size >= gb_to_bytes(config["mdswh"]): root_end = int((size * 0.35) / (1000**2)) else: root_end = get_min_root_size() if (efi and (part1 is None)): part1 = __make_efi__(device) part2 = __make_root__(device, end=root_end) part3 = __make_home__(device, new_start=root_end) elif part1 is None: part1 = __make_root__(device, start="0%", end=root_end) __make_root_boot__(device) part2 = __make_home__(device, new_start=root_end) common.eprint("\t###\tauto_partioner.py CLOSED\t###\t") return __generate_return_data__(home, efi, part1, part2, part3) if home in ("NULL", "null", None): # If home == any possible 'null' value, # we KNOW there are no partitons because we made a # new partition table if efi: part1 = __make_efi__(device) part2 = __make_root__(device, end="100%") else: part1 = __make_root__(device, start="0%", end="100%") __make_root_boot__(device) common.eprint("\t###\tauto_partioner.py CLOSED\t###\t") return __generate_return_data__(home, efi, part1, part2, part3) # This one we need to figure out if the home partiton is on the drive # we are working on or elsewhere if root == get_drive_path(home): # It IS on the same drive. We need to figure out where at and work # around it # NOTE: WE NEED TO WORK IN MB ONLY IN THIS SECTION disk = parted.Disk(device) data = disk.getFreeSpaceRegions() sizes = {} for each in data: sizes[each.length] = each sizes_sorted = sorted(sizes) # Lets make some partitons! if efi: for each in sizes_sorted: if sizes[each].getSize() >= 200: end = sizes[each].start + parted.sizeToSectors( 200, "MB", device.sectorSize) end = sectors_to_size(end, device.sectorSize) part1 = __make_efi__(device, start=sizes[each].start, end=end) part2 = __make_root__(device, start=end, end=sizes[each].end) break else: for each in sizes_sorted: if sizes[each].getSize() >= 200: part1 = __make_root__(device, start=sizes[each].start + 1, end=sizes[each].end - 1) __make_root_boot__(device) break common.eprint("\t###\tauto_partioner.py CLOSED\t###\t") return __generate_return_data__(home, efi, part1, part2, part3) # it's elsewhere. We're good. if efi: part1 = __make_efi__(device) part2 = __make_root__(device, end="100%") else: part1 = __make_root__(device, start="0%", end="100%") __make_root_boot__(device) part3 = home # Figure out what parts are for what # Return that data as a dictonary common.eprint("\t###\tauto_partioner.py CLOSED\t###\t") return __generate_return_data__(home, efi, part1, part2, part3)
def partition_reset(self, dev: Dict[str, Any]): """ Repartition the SD card from scratch """ try: import parted except ModuleNotFoundError: raise Fail("please install python3-parted") device = parted.getDevice(dev["path"]) device.clobber() disk = parted.freshDisk(device, "msdos") # Add 256M fat boot optimal = device.optimumAlignment constraint = parted.Constraint( startAlign=optimal, endAlign=optimal, startRange=parted.Geometry( device=device, start=parted.sizeToSectors(4, "MiB", device.sectorSize), end=parted.sizeToSectors(16, "MiB", device.sectorSize)), endRange=parted.Geometry( device=device, start=parted.sizeToSectors(256, "MiB", device.sectorSize), end=parted.sizeToSectors(512, "MiB", device.sectorSize)), minSize=parted.sizeToSectors(256, "MiB", device.sectorSize), maxSize=parted.sizeToSectors(260, "MiB", device.sectorSize)) geometry = parted.Geometry( device, start=0, length=parted.sizeToSectors(256, "MiB", device.sectorSize), ) geometry = constraint.solveNearest(geometry) boot = parted.Partition( disk=disk, type=parted.PARTITION_NORMAL, fs=parted.FileSystem(type='fat32', geometry=geometry), geometry=geometry) boot.setFlag(parted.PARTITION_LBA) disk.addPartition(partition=boot, constraint=constraint) # Add 4G ext4 rootfs constraint = parted.Constraint( startAlign=optimal, endAlign=optimal, startRange=parted.Geometry( device=device, start=geometry.end, end=geometry.end + parted.sizeToSectors(16, "MiB", device.sectorSize)), endRange=parted.Geometry( device=device, start=geometry.end + parted.sizeToSectors(4, "GiB", device.sectorSize), end=geometry.end + parted.sizeToSectors(4.2, "GiB", device.sectorSize)), minSize=parted.sizeToSectors(4, "GiB", device.sectorSize), maxSize=parted.sizeToSectors(4.2, "GiB", device.sectorSize)) geometry = parted.Geometry( device, start=geometry.start, length=parted.sizeToSectors(4, "GiB", device.sectorSize), ) geometry = constraint.solveNearest(geometry) rootfs = parted.Partition( disk=disk, type=parted.PARTITION_NORMAL, fs=parted.FileSystem(type='ext4', geometry=geometry), geometry=geometry) disk.addPartition(partition=rootfs, constraint=constraint) # Add media partition on the rest of the disk constraint = parted.Constraint( startAlign=optimal, endAlign=optimal, startRange=parted.Geometry( device=device, start=geometry.end, end=geometry.end + parted.sizeToSectors(16, "MiB", device.sectorSize)), endRange=parted.Geometry( device=device, start=geometry.end + parted.sizeToSectors(16, "MiB", device.sectorSize), end=disk.maxPartitionLength), minSize=parted.sizeToSectors(4, "GiB", device.sectorSize), maxSize=disk.maxPartitionLength) geometry = constraint.solveMax() # Create media partition media = parted.Partition( disk=disk, type=parted.PARTITION_NORMAL, geometry=geometry) disk.addPartition(partition=media, constraint=constraint) disk.commit() time.sleep(0.5) # Fix disk identifier to match what is in cmdline.txt with open(dev["path"], "r+b") as fd: buf = bytearray(512) fd.readinto(buf) buf[0x1B8] = 0x13 buf[0x1B9] = 0x6e buf[0x1BA] = 0x58 buf[0x1BB] = 0x6c fd.seek(0) fd.write(buf) time.sleep(0.5) # Format boot partition with 'boot' label run(["mkfs.fat", "-F", "32", "-n", "boot", disk.partitions[0].path]) # Format rootfs partition with 'rootfs' label run(["mkfs.ext4", "-F", "-L", "rootfs", "-O", "^64bit,^huge_file,^metadata_csum", disk.partitions[1].path]) # Format exfatfs partition with 'media' label run(["mkexfatfs", "-n", "media", disk.partitions[2].path])
def enter(self): if not self.should_enter(): return self.context.logger.log("Entering split_root_partition state") device = parted.getDevice(self.rootfs_disk) disk = parted.newDisk(device) original_root_fs_size = self._get_root_fs_size_in(device.sectorSize) self.context.logger.log("Original root filesystem size (sectors): {0}".format(original_root_fs_size)) desired_boot_partition_size = parted.sizeToSectors(256, 'MiB', device.sectorSize) self.context.logger.log("Desired boot partition size (sectors): {0}".format(desired_boot_partition_size)) desired_root_fs_size = int(original_root_fs_size - desired_boot_partition_size) self.context.logger.log("Desired root filesystem size (sectors): {0}".format(desired_root_fs_size)) attempt = 1 while attempt < 10: resize_result = self.command_executor.Execute("resize2fs {0} {1}s".format(self.rootfs_block_device, desired_root_fs_size)) if resize_result == 0: break else: self.command_executor.Execute('systemctl restart systemd-udevd') self.command_executor.Execute('systemctl restart systemd-timesyncd') self.command_executor.Execute('udevadm trigger') sleep(10) attempt += 1 resized_root_fs_size = self._get_root_fs_size_in(device.sectorSize) self.context.logger.log("Resized root filesystem size (sectors): {0}".format(resized_root_fs_size)) if not desired_root_fs_size == resized_root_fs_size: raise Exception("resize2fs failed, desired: {0}, resized: {1}".format(desired_root_fs_size, resized_root_fs_size)) self.context.logger.log("Root filesystem resized successfully") root_partition = disk.getPartitionByPath(os.path.realpath(self.rootfs_block_device)) original_root_partition_start = root_partition.geometry.start original_root_partition_end = root_partition.geometry.end self.context.logger.log("Original root partition start (sectors): {0}".format(original_root_partition_start)) self.context.logger.log("Original root partition end (sectors): {0}".format(original_root_partition_end)) desired_root_partition_start = original_root_partition_start desired_root_partition_end = original_root_partition_end - desired_boot_partition_size desired_root_partition_size = desired_root_partition_end - desired_root_partition_start self.context.logger.log("Desired root partition start (sectors): {0}".format(desired_root_partition_start)) self.context.logger.log("Desired root partition end (sectors): {0}".format(desired_root_partition_end)) self.context.logger.log("Desired root partition size (sectors): {0}".format(desired_root_partition_size)) desired_root_partition_geometry = parted.Geometry(device=device, start=desired_root_partition_start, length=desired_root_partition_size) root_partition_constraint = parted.Constraint(exactGeom=desired_root_partition_geometry) disk.setPartitionGeometry(partition=root_partition, constraint=root_partition_constraint, start=desired_root_partition_start, end=desired_root_partition_end) desired_boot_partition_start = disk.getFreeSpaceRegions()[1].start desired_boot_partition_end = disk.getFreeSpaceRegions()[1].end desired_boot_partition_size = disk.getFreeSpaceRegions()[1].length self.context.logger.log("Desired boot partition start (sectors): {0}".format(desired_boot_partition_start)) self.context.logger.log("Desired boot partition end (sectors): {0}".format(desired_boot_partition_end)) desired_boot_partition_geometry = parted.Geometry(device=device, start=desired_boot_partition_start, length=desired_boot_partition_size) boot_partition_constraint = parted.Constraint(exactGeom=desired_boot_partition_geometry) desired_boot_partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=desired_boot_partition_geometry) if (root_partition.getFlag(parted.PARTITION_BOOT)): desired_boot_partition.setFlag(parted.PARTITION_BOOT) disk.addPartition(partition=desired_boot_partition, constraint=boot_partition_constraint) disk.commit() probed_root_fs = parted.probeFileSystem(desired_root_partition_geometry) if not probed_root_fs == 'ext4': raise Exception("Probed root fs is not ext4") self.command_executor.Execute("partprobe", True) self.command_executor.Execute("mkfs.ext2 {0}".format(self.bootfs_block_device), True) boot_partition_uuid = self._get_uuid(self.bootfs_block_device) # Move stuff from /oldroot/boot to new partition, make new partition mountable at the same spot self.command_executor.Execute("mount {0} /oldroot".format(self.rootfs_block_device), True) self.command_executor.Execute("mkdir -p /boot", True) self.command_executor.Execute("cp /oldroot/etc/fstab /etc/fstab", True) self._append_boot_partition_uuid_to_fstab(boot_partition_uuid) self.command_executor.Execute("cp /etc/fstab /oldroot/etc/fstab", True) self.command_executor.Execute("mount /boot", True) self.command_executor.ExecuteInBash("mv /oldroot/boot/* /boot/", True) self.command_executor.Execute("umount /boot", True) self.command_executor.Execute("umount /oldroot", True)
def apply(self, disk, simulate): try: nlen = parted.sizeToSectors(self.their_size, 'B', disk.device.sectorSize) cmd = None if self.part.fileSystem.type == "ntfs": newSz = str(int(self.their_size) / 1000) prefix = "/usr/sbin" check_cmd = "{}/ntfsresize -i -f --force -v {} {}".format( prefix, "--no-action" if simulate else "", self.part.path) resize_cmd = "{}/ntfsresize {} -f -f -b --size {}k {}".format( prefix, "--no-action" if simulate else "", newSz, self.part.path) # Check first try: subprocess.check_call(check_cmd, shell=True) except Exception as e: self.set_errors(e) return False # Now resize it try: subprocess.check_call(resize_cmd, shell=True) except Exception as e: self.set_errors(e) return False (c, geom) = self.get_size_constraint(disk, nlen) self.part.disk.setPartitionGeometry(partition=self.part, constraint=c, start=geom.start, end=geom.end) self.new_part_off = geom.end # All done return True elif self.part.fileSystem.type.startswith("ext"): if simulate: (c, geom) = self.get_size_constraint(disk, nlen) self.part.disk.setPartitionGeometry(partition=self.part, constraint=c, start=geom.start, end=geom.end) self.new_part_off = geom.end return True # check it first cmd1 = "/sbin/e2fsck -f -p {}".format(self.part.path) try: subprocess.check_call(cmd1, shell=True) except Exception as ex: print(ex) self.set_errors(ex) return False new_size = str(int(self.their_size / 1024)) cmd = "/sbin/resize2fs {} {}K".format(self.part.path, new_size) try: subprocess.check_call(cmd, shell=True) except Exception as ex: print(ex) self.set_errors(ex) return False (c, geom) = self.get_size_constraint(disk, nlen) self.part.disk.setPartitionGeometry(partition=self.part, constraint=c, start=geom.start, end=geom.end) self.new_part_off = geom.end else: return False except Exception as e: self.set_errors(e) return False return True
def _kib_to_sectors(self,device, kib): return parted.sizeToSectors(kib, 'KiB', device.sectorSize)
def enter(self): if not self.should_enter(): return self.context.logger.log("Entering split_root_partition state") device = parted.getDevice('/dev/sda') disk = parted.newDisk(device) original_root_fs_size = self._get_root_fs_size_in(device.sectorSize) self.context.logger.log( "Original root filesystem size (sectors): {0}".format( original_root_fs_size)) desired_boot_partition_size = parted.sizeToSectors( 256, 'MiB', device.sectorSize) self.context.logger.log( "Desired boot partition size (sectors): {0}".format( desired_boot_partition_size)) desired_root_fs_size = original_root_fs_size - desired_boot_partition_size self.context.logger.log( "Desired root filesystem size (sectors): {0}".format( desired_root_fs_size)) self.command_executor.Execute( "resize2fs /dev/sda1 {0}s".format(desired_root_fs_size), True) resized_root_fs_size = self._get_root_fs_size_in(device.sectorSize) self.context.logger.log( "Resized root filesystem size (sectors): {0}".format( resized_root_fs_size)) if not desired_root_fs_size == resized_root_fs_size: raise Exception( "resize2fs failed, desired: {0}, resized: {1}".format( desired_root_fs_size, resized_root_fs_size)) self.context.logger.log("Root filesystem resized successfully") root_partition = disk.partitions[0] original_root_partition_start = root_partition.geometry.start original_root_partition_end = root_partition.geometry.end self.context.logger.log( "Original root partition start (sectors): {0}".format( original_root_partition_start)) self.context.logger.log( "Original root partition end (sectors): {0}".format( original_root_partition_end)) desired_root_partition_start = original_root_partition_start desired_root_partition_end = original_root_partition_end - desired_boot_partition_size desired_root_partition_size = desired_root_partition_end - desired_root_partition_start self.context.logger.log( "Desired root partition start (sectors): {0}".format( desired_root_partition_start)) self.context.logger.log( "Desired root partition end (sectors): {0}".format( desired_root_partition_end)) self.context.logger.log( "Desired root partition size (sectors): {0}".format( desired_root_partition_size)) desired_root_partition_geometry = parted.Geometry( device=device, start=desired_root_partition_start, length=desired_root_partition_size) root_partition_constraint = parted.Constraint( exactGeom=desired_root_partition_geometry) disk.setPartitionGeometry(partition=root_partition, constraint=root_partition_constraint, start=desired_root_partition_start, end=desired_root_partition_end) desired_boot_partition_start = disk.getFreeSpaceRegions()[1].start desired_boot_partition_end = disk.getFreeSpaceRegions()[1].end desired_boot_partition_size = disk.getFreeSpaceRegions()[1].length self.context.logger.log( "Desired boot partition start (sectors): {0}".format( desired_boot_partition_start)) self.context.logger.log( "Desired boot partition end (sectors): {0}".format( desired_boot_partition_end)) desired_boot_partition_geometry = parted.Geometry( device=device, start=desired_boot_partition_start, length=desired_boot_partition_size) boot_partition_constraint = parted.Constraint( exactGeom=desired_boot_partition_geometry) desired_boot_partition = parted.Partition( disk=disk, type=parted.PARTITION_NORMAL, geometry=desired_boot_partition_geometry) disk.addPartition(partition=desired_boot_partition, constraint=boot_partition_constraint) disk.commit() probed_root_fs = parted.probeFileSystem(disk.partitions[0].geometry) if not probed_root_fs == 'ext4': raise Exception("Probed root fs is not ext4") disk.partitions[1].setFlag(parted.PARTITION_BOOT) disk.commit() self.command_executor.Execute("partprobe", True) self.command_executor.Execute("mkfs.ext2 /dev/sda2", True) boot_partition_uuid = self._get_uuid("/dev/sda2") # Move stuff from /oldroot/boot to new partition, make new partition mountable at the same spot self.command_executor.Execute("mount /dev/sda1 /oldroot", True) self.command_executor.Execute("mkdir /oldroot/memroot", True) self.command_executor.Execute("mount --make-rprivate /", True) self.command_executor.Execute("pivot_root /oldroot /oldroot/memroot", True) self.command_executor.ExecuteInBash( "for i in dev proc sys; do mount --move /memroot/$i /$i; done", True) self.command_executor.Execute("mv /boot /boot.backup", True) self.command_executor.Execute("mkdir /boot", True) self._append_boot_partition_uuid_to_fstab(boot_partition_uuid) self.command_executor.Execute("cp /etc/fstab /memroot/etc/fstab", True) self.command_executor.Execute("mount /boot", True) self.command_executor.ExecuteInBash("mv /boot.backup/* /boot/", True) self.command_executor.Execute("rmdir /boot.backup", True) self.command_executor.Execute("mount --make-rprivate /", True) self.command_executor.Execute("pivot_root /memroot /memroot/oldroot", True) self.command_executor.Execute("rmdir /oldroot/memroot", True) self.command_executor.ExecuteInBash( "for i in dev proc sys; do mount --move /oldroot/$i /$i; done", True) self.command_executor.Execute("systemctl restart rsyslog", True) self.command_executor.Execute("systemctl restart systemd-udevd", True) self.command_executor.Execute("systemctl restart walinuxagent", True) self.command_executor.Execute("umount /oldroot/boot", True) self.command_executor.Execute("umount /oldroot", True)
def apply(self, disk, simulate): try: nlen = parted.sizeToSectors(self.their_size, 'B', disk.device.sectorSize) cmd = None if self.part.fileSystem.type == "ntfs": newSz = str(int(self.their_size) / 1000) prefix = "/usr/sbin" check_cmd = "{}/ntfsresize -i -f --force -v {} {}".format( prefix, "--no-action" if simulate else "", self.part.path) resize_cmd = "{}/ntfsresize {} -f -f -b --size {}k {}".format( prefix, "--no-action" if simulate else "", newSz, self.part.path) # Check first try: subprocess.check_call(check_cmd, shell=True) except Exception as e: self.set_errors(e) return False # Now resize it try: subprocess.check_call(resize_cmd, shell=True) except Exception as e: self.set_errors(e) return False (c, geom) = self.get_size_constraint(disk, nlen) self.part.disk.setPartitionGeometry(partition=self.part, constraint=c, start=geom.start, end=geom.end) self.new_part_off = geom.end # All done return True elif self.part.fileSystem.type.startswith("ext"): if simulate: (c, geom) = self.get_size_constraint(disk, nlen) self.part.disk.setPartitionGeometry(partition=self.part, constraint=c, start=geom.start, end=geom.end) self.new_part_off = geom.end return True # check it first cmd1 = "/sbin/e2fsck -f -p {}".format(self.part.path) try: subprocess.check_call(cmd1, shell=True) except Exception as ex: print(ex) self.set_errors(ex) return False new_size = str(int(self.their_size / 1024)) cmd = "/sbin/resize2fs {} {}K".format( self.part.path, new_size) try: subprocess.check_call(cmd, shell=True) except Exception as ex: print(ex) self.set_errors(ex) return False (c, geom) = self.get_size_constraint(disk, nlen) self.part.disk.setPartitionGeometry(partition=self.part, constraint=c, start=geom.start, end=geom.end) self.new_part_off = geom.end else: return False except Exception as e: self.set_errors(e) return False return True
def enter(self): if not self.should_enter(): return self.context.logger.log("Entering split_root_partition state") device = parted.getDevice(self.rootfs_disk) disk = parted.Disk(device) original_root_fs_size = self._get_root_fs_size_in(device.sectorSize) self.context.logger.log( "Original root filesystem size (sectors): {0}".format( original_root_fs_size)) desired_boot_partition_size = parted.sizeToSectors( 256, 'MiB', device.sectorSize) self.context.logger.log( "Desired boot partition size (sectors): {0}".format( desired_boot_partition_size)) root_partition = disk.partitions[0] original_root_partition_start = root_partition.geometry.start original_root_partition_end = root_partition.geometry.end self.context.logger.log( "Original root partition start (sectors): {0}".format( original_root_partition_start)) self.context.logger.log( "Original root partition end (sectors): {0}".format( original_root_partition_end)) desired_root_partition_start = original_root_partition_start desired_root_partition_end = original_root_partition_end - desired_boot_partition_size desired_root_partition_size = desired_root_partition_end - desired_root_partition_start self.context.logger.log( "Desired root partition start (sectors): {0}".format( desired_root_partition_start)) self.context.logger.log( "Desired root partition end (sectors): {0}".format( desired_root_partition_end)) self.context.logger.log( "Desired root partition size (sectors): {0}".format( desired_root_partition_size)) self.context.logger.log("Resizing root filesystem") desired_root_fs_size = desired_root_partition_size self._resize_root_fs_to_sectors(desired_root_fs_size, device.sectorSize) desired_root_partition_geometry = parted.Geometry( device=device, start=desired_root_partition_start, length=desired_root_partition_size) root_partition_constraint = parted.Constraint( exactGeom=desired_root_partition_geometry) disk.setPartitionGeometry(partition=root_partition, constraint=root_partition_constraint, start=desired_root_partition_start, end=desired_root_partition_end) desired_boot_partition_start = disk.getFreeSpaceRegions()[1].start desired_boot_partition_end = disk.getFreeSpaceRegions()[1].end desired_boot_partition_size = disk.getFreeSpaceRegions()[1].length self.context.logger.log( "Desired boot partition start (sectors): {0}".format( desired_boot_partition_start)) self.context.logger.log( "Desired boot partition end (sectors): {0}".format( desired_boot_partition_end)) desired_boot_partition_geometry = parted.Geometry( device=device, start=desired_boot_partition_start, length=desired_boot_partition_size) boot_partition_constraint = parted.Constraint( exactGeom=desired_boot_partition_geometry) desired_boot_partition = parted.Partition( disk=disk, type=parted.PARTITION_NORMAL, geometry=desired_boot_partition_geometry) disk.addPartition(partition=desired_boot_partition, constraint=boot_partition_constraint) disk.commit() probed_root_fs = parted.probeFileSystem(disk.partitions[0].geometry) if not probed_root_fs == 'ext4': raise Exception("Probed root fs is not ext4") disk.partitions[1].setFlag(parted.PARTITION_BOOT) disk.commit() self.command_executor.Execute("partprobe", False) self.command_executor.Execute( "mkfs.ext2 {0}".format(self.bootfs_block_device), True) boot_partition_uuid = self._get_uuid(self.bootfs_block_device) # Move stuff from /oldroot/boot to new partition, make new partition mountable at the same spot self.command_executor.Execute( "mount {0} /oldroot".format(self.rootfs_block_device), True) self.command_executor.Execute("mkdir /oldroot/memroot", True) self.command_executor.Execute("mount --make-rprivate /", True) self.command_executor.Execute("pivot_root /oldroot /oldroot/memroot", True) self.command_executor.ExecuteInBash( "for i in dev proc sys; do mount --move /memroot/$i /$i; done", True) self.command_executor.Execute("mv /boot /boot.backup", True) self.command_executor.Execute("mkdir /boot", True) self._append_boot_partition_uuid_to_fstab(boot_partition_uuid) self.command_executor.Execute("cp /etc/fstab /memroot/etc/fstab", True) self.command_executor.Execute("mount /boot", True) self.command_executor.ExecuteInBash("mv /boot.backup/* /boot/", True) self.command_executor.Execute("rmdir /boot.backup", True) self.command_executor.Execute("mount --make-rprivate /", True) self.command_executor.Execute("pivot_root /memroot /memroot/oldroot", True) self.command_executor.Execute("rmdir /oldroot/memroot", True) self.command_executor.ExecuteInBash( "for i in dev proc sys; do mount --move /oldroot/$i /$i; done", True) self.command_executor.Execute("service rsyslog restart", True) self.command_executor.Execute("service udev restart", True) self.command_executor.Execute("umount /oldroot/boot", True) try: self.command_executor.Execute("umount /oldroot", True) except: self.context.logger.log( "Could not unmount /oldroot, attempting to restart WALA and unmount again" ) self.should_exit() self.context.logger.log("Removing marker for UnmountOldrootState") os.unlink( os.path.join( self.context.encryption_environment. os_encryption_markers_path, 'UnmountOldrootState')) self.command_executor.Execute( 'at -f /restart-wala.sh now + 1 minutes', True) self.command_executor.Execute('service walinuxagent stop', True)