def runTest(self): # Test that passing the kwargs to __init__ works. self.assertEqual(self.part.disk, self.disk) self.assertIsInstance(self.part.geometry, parted.Geometry) self.assertEqual(self.part.type, parted.PARTITION_NORMAL) self.assertEqual(self.part.fileSystem.type, "ext2") # Test that setting the RW attributes directly works. self.part.type = parted.PARTITION_EXTENDED self.assertEqual(self.part.type, parted.PARTITION_EXTENDED) # Test that setting the RO attributes directly doesn't work. exn = (AttributeError, TypeError) with self.assertRaises(exn): self.part.number = 1 with self.assertRaises(exn): self.part.active = True with self.assertRaises(exn): self.part.name = "blah" with self.assertRaises(exn): self.part.type = "blah" with self.assertRaises(exn): self.part.geometry = parted.Geometry(self.device, start=10, length=20) with self.assertRaises(exn): self.part.fileSystem = parted.FileSystem(type='ext4', geometry=self.geom) with self.assertRaises(exn): self.part.disk = self.disk # Check that looking for invalid attributes fails properly. with self.assertRaises((AttributeError)): print(self.part.blah)
def get_partition_by_path(self, path, fs_type): """ """ p = self.getPartitionByPath(path) fs = parted.FileSystem(fs_type, p.geometry) p.fileSystem = fs partition = self._instance_partition(p) return partition
def __init__(self, disk=None, type=None, fs=None, geometry=None, PedPartition=None): if PedPartition is None: if disk is None: raise parted.PartitionException("no disk specified") elif type is None: raise parted.PartitionException("no type specified") elif geometry is None: raise parted.PartitionException("no geometry specified") self._fileSystem = fs self._geometry = geometry self._disk = disk if fs is None: self.__partition = _ped.Partition(disk.getPedDisk(), type, geometry.start, geometry.end) else: self.__partition = _ped.Partition(disk.getPedDisk(), type, geometry.start, geometry.end, parted.fileSystemType[fs.type]) else: self.__partition = PedPartition self._geometry = parted.Geometry(PedGeometry=self.__partition.geom) if disk is None: self._disk = parted.Disk(PedDisk=self.__partition.disk) else: self._disk = disk if self.__partition.fs_type is None: self._fileSystem = None else: self._fileSystem = parted.FileSystem(type=self.__partition.fs_type.name, geometry=self._geometry)
def putGeom(self, limPartList): #Write the disk geometry information #Template code @ https://bitbucket.org/rbistolfi/vinstall/wiki/pyparted disk = parted.freshDisk(self.dev, "msdos") for lpar in limPartList: if lpar.parttype != 'artificial': #TODO: should check that the geometry is within the disk g = parted.Geometry(device=self.dev, start=lpar.start, end=lpar.end) fs = parted.FileSystem(type=lpar.fstype, geometry=g) #TODO: eventually we should be able to handle logical/extended #partitions - right now it's primary only ptype = parted.PARTITION_NORMAL if lpar.parttype != 'primary': raise errors.partError(lpar.parttype) p = parted.Partition(disk=disk, fs=fs, type=ptype, geometry=g) c = parted.Constraint(exactGeom=g) disk.addPartition(partition=p, constraint=c) setFlags(p, lpar.flags) disk.commit() #refresh the OS's view of the disk support.partprobe(self.node) #put file systems onto the new partitions for lpar in limPartList: if lpar.parttype != 'artificial': support.mkfs(lpar.composeNode(self.node), lpar.fstype)
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 partitionAdd(self, disk, free, align=None, length=None, fs_type=None, type=parted.PARTITION_NORMAL): start = free.start if length: end = start + length - 1 else: end = free.end length = free.end - start + 1 if not align: align = disk.partitionAlignment.intersect( disk.device.optimumAlignment) if not align.isAligned(free, start): start = align.alignNearest(free, start) end_align = parted.Alignment(offset=align.offset - 1, grainSize=align.grainSize) if not end_align.isAligned(free, end): end = end_align.alignNearest(free, end) geometry = parted.Geometry(disk.device, start=start, end=end) if fs_type: fs = parted.FileSystem(type=fs_type, geometry=geometry) else: fs = None partition = parted.Partition(disk, type=type, geometry=geometry, fs=fs) constraint = parted.Constraint(exactGeom=partition.geometry) disk.addPartition(partition, constraint) return partition
def partition(self): """ Create a partition table on the block device. The newly created partition will have the following characteristics: - a primary partition using 100% of the device capacity - optimal alignment given the disk topology information - a MS-DOS disk label for simple BIOS booting on PC-type hardware - marked as bootable """ self.logger.info('creating primary partition') device = parted.getDevice(self.path) self.logger.debug('created %s', device) disk = parted.freshDisk(device, 'msdos') self.logger.debug('created %s', disk) geometry = parted.Geometry(device=device, start=1, length=device.getLength() - 1) self.logger.debug('created %s', geometry) filesystem = parted.FileSystem(type='ext3', geometry=geometry) self.logger.debug('created %s', filesystem) partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=filesystem, geometry=geometry) self.logger.debug('created %s', partition) disk.addPartition(partition=partition, constraint=device.optimalAlignedConstraint) partition.setFlag(parted.PARTITION_BOOT) disk.commit()
def setUp(self): super(PartitionGPTNewTestCase, self).setUp() self.geom = parted.Geometry(self.device, start=100, length=100) self.fs = parted.FileSystem(type='ext2', geometry=self.geom) self.part = parted.Partition(self.disk, parted.PARTITION_NORMAL, geometry=self.geom, fs=self.fs)
def get_partition_by_number(self, number, fs_type): """ """ for p in self.partitions: if p.number == number: fs = parted.FileSystem(fs_type, p.geometry) p.fileSystem = fs partition = self._instance_partition(p) return partition return None
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 createpartition(self, device, disk, start, end, type): ''' Create a single partition of the specified type and size and add it to the disk object, using the parted module. ''' geo = parted.Geometry(device=device, start=start, end=end) fs = parted.FileSystem(type=type, geometry=geo) part = parted.Partition(disk=disk, fs=fs, type=parted.PARTITION_NORMAL, geometry=geo) constraint = parted.Constraint(exactGeom=geo) disk.addPartition(partition=part, constraint=constraint)
def create_partitioning(device): """Returns a suitable partitioning (a disk) of the given device. You must specify device path (e.g. "/dev/sda"). Note that no changes will be made to the device. To write the partition to device use commit.""" disk = parted.freshDisk(device, 'gpt') geometries = _compute_geometries(device) # Create ESP esp = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=parted.FileSystem(type='fat32', geometry=geometries['esp']), geometry=geometries['esp']) esp.setFlag(parted.PARTITION_BOOT) disk.addPartition(partition=esp, constraint=device.optimalAlignedConstraint) # Create Data partition data = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=parted.FileSystem(type='ext4', geometry=geometries['data']), geometry=geometries['data']) disk.addPartition(partition=data, constraint=device.optimalAlignedConstraint) # Create system.a partition systemA = parted.Partition( disk=disk, type=parted.PARTITION_NORMAL, fs=parted.FileSystem(type='ext4', geometry=geometries['systemA']), geometry=geometries['systemA']) disk.addPartition(partition=systemA, constraint=device.optimalAlignedConstraint) # Create system.b partition systemB = parted.Partition( disk=disk, type=parted.PARTITION_NORMAL, fs=parted.FileSystem(type='ext4', geometry=geometries['systemB']), geometry=geometries['systemB']) disk.addPartition(partition=systemB, constraint=device.optimalAlignedConstraint) return (disk)
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 create_partition(disk: parted.Disk, start, end, fscode, fstype=None): log.info(f'Creating partition ({start}-{end}) type {fscode}') geometry = parted.Geometry(device=disk.device, start=start, end=end) new_partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=parted.FileSystem(type=fscode, geometry=geometry), geometry=geometry) if not disk.addPartition(partition=new_partition, constraint=parted.Constraint(exactGeom=geometry)): die(f'Creating partition failed') disk.commit() if fstype: sh(f'mkfs.{fstype}', new_partition.path)
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 _new_partition(self, device, disk, start, length, set_boot=False): geometry = parted.Geometry(device=device, start=start, length=length) self.logger.debug('created %s', geometry) filesystem = parted.FileSystem(type='ext4', geometry=geometry) self.logger.debug('created %s', filesystem) partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=filesystem, geometry=geometry) self.logger.debug('created %s', partition) disk.addPartition(partition=partition, constraint=device.optimalAlignedConstraint) if set_boot: partition.setFlag(parted.PARTITION_BOOT) return partition
def partition(device): dev = parted.Device(path=device) disk = parted.freshDisk(dev, 'msdos') constraint = parted.Constraint(device=dev) new_geom = parted.Geometry(device=dev, start=1, end=(constraint.maxSize - 1)) filesystem = parted.FileSystem(type="ext2", geometry=new_geom) partition = parted.Partition(disk=disk, fs=filesystem, type=parted.PARTITION_NORMAL, geometry=new_geom) constraint = parted.Constraint(exactGeom=new_geom) partition.setFlag(parted.PARTITION_BOOT) disk.addPartition(partition=partition, constraint=constraint) disk.commit()
def partition(device): """Recieves a device object. Wipes the device and creates a single partition.""" wipe(device) disk = parted.freshDisk(device, 'msdos') geometry = parted.Geometry(device=device, start=1, length=device.getLength() - 1) filesystem = parted.FileSystem(type='ext4', geometry=geometry) partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=filesystem, geometry=geometry) disk.addPartition(partition=partition, constraint=device.optimalAlignedConstraint) partition.setFlag(parted.PARTITION_BOOT) disk.commit()
def appendSizedExt4PartitionOptimizedForMicroSDHC(parted_disk, desired_size_bytes=None): if len(parted_disk.partitions) >= parted_disk.maxSupportedPartitionCount: return ## get largest free region parted_largestfreeregion_geometry = max(parted_disk.getFreeSpaceRegions(), key=lambda x: x.getLength()) ## define optimum settings for micrSDHC card (first 4MiB contains only MBR and everything aligned to 4MiB) optAlignmentForRasperry = parted_disk.device.optimumAlignment optAlignmentForRasperry.offset = int(4 * 1024**2 / parted_disk.device.sectorSize) #8192 optAlignmentForRasperry.grainSize = int( 4 * 1024**2 / parted_disk.device.sectorSize) #8192 assert (optAlignmentForRasperry.offset == 8192) assert (optAlignmentForRasperry.grainSize == 8192) #leave space between partitions newstart = optAlignmentForRasperry.alignUp( parted_largestfreeregion_geometry, parted_largestfreeregion_geometry.start) newend = parted_largestfreeregion_geometry.end if not desired_size_bytes is None: new_size_sectors = int(desired_size_bytes / parted_disk.device.sectorSize) newend = optAlignmentForRasperry.alignDown( parted_largestfreeregion_geometry, newstart + new_size_sectors) parted_newpartition_geometry = parted.Geometry(device=parted_disk.device, start=newstart, end=newend) parted_appended_partition = parted.Partition( disk=parted_disk, type=parted.PARTITION_NORMAL, fs=parted.FileSystem(type='ext4', geometry=parted_newpartition_geometry), geometry=parted_newpartition_geometry) parted_disk.addPartition(partition=parted_appended_partition, constraint=parted.Constraint( exactGeom=parted_appended_partition.geometry))
def _create_partition(self, region, start, end, format_type, type=parted.PARTITION_NORMAL): """Creates the partition with geometry specified""" # libparted doesn't let setting partition number, so we skip it, too # We want our new partition to be optimally aligned # (you can use minimalAlignedConstraint, if you wish). alignment = self.device.optimalAlignedConstraint constraint = self.device.getConstraint().intersect(alignment) # parted.Constraint(maxGeom=region).intersect(alignment) data = { 'start': constraint.startAlign.alignUp(region, region.start), 'end': constraint.endAlign.alignDown(region, region.end), } part_start = int(start) # check sur data['start'] part_end = self._parse_last_sector_expr( part_start, end, self.device.sectorSize) # self._ask_value( # check sur data['end'] try: geometry = parted.Geometry( device=self.device, start=part_start, end=part_end) fs = parted.FileSystem(type=format_type, geometry=geometry) partition = parted.Partition( disk=self.disk, type=type, geometry=geometry, fs=fs ) 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) return partition
def _makeVDisk(self): self.parts = [('p1', 'junk')] self.image_file = self.path os_call([ 'dd', 'bs=4096', 'count=5000', 'if=/dev/zero', 'of=' + self.image_file ]) with subprocess.Popen(['sudo', 'losetup', '-f'], stdout=subprocess.PIPE, universal_newlines=True) as lo_list: out = lo_list.stdout.read().split('\n')[:-1] if len(out) > 0: self.path = out[0] else: self.path = '/dev/loop0' self.part_prefix = 'p' os_call(['sudo', 'losetup', '-P', self.path, self.image_file]) self.device = parted.getDevice(self.path) disk = parted.freshDisk(self.device, 'msdos') geom = parted.Geometry(self.device, start=1, length=self.device.getLength() - 1) fs = parted.FileSystem('fat16', geom) new_part = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=fs, geometry=geom) disk.addPartition(partition=new_part, constraint=self.device.getConstraint()) new_part.setFlag(parted.PARTITION_BOOT) try: disk.commit() except: pass self.format(mk_vfat(), 0) self.parts = self.partitions() self.__undoLo = ['sudo', 'losetup', '-d', self.path]
def create_usb_partitions(self): # Code earlier has verified that usb drive is unmounted. self.wipe_old_partitions() subprocess.check_call('sync') device = parted.getDevice(self.usb_device_name) disk = parted.freshDisk(device, 'msdos') constraint = parted.Constraint(device=device) geometry = parted.Geometry(device=device, start=1, end=(constraint.maxSize - 1)) filesystem = parted.FileSystem(type='fat32', geometry=geometry) partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=filesystem, geometry=geometry) disk.addPartition(partition=partition, constraint=device.optimalAlignedConstraint) partition.setFlag(parted.PARTITION_BOOT) disk.commit() subprocess.check_call('sync') import time time.sleep( 5) # The kernel seems to take a while to detect new partitions. subprocess.check_call(['mkfs.vfat', self.usb_partition])
def add_partition(self, start, end, fstype, flags, ptype): """ Create a specified partition by start and end sectors. :param start: The sector the partition will start at. :param end: The sector the partition will end at. :param fstype: The fstype of the partition if it's valid. :param flags: The flags to set on the partition. :param ptype: The type of partition it should be. :return: """ # An array of a few fs that aren't actually valid parted fs's. bad_fs = [ 'LVM2_member', 'swap', 'linux_raid_member', 'vfat', 'crypto_LUKS' ] try: # Set the partition type. if ptype == 0: p_type = parted.PARTITION_NORMAL elif ptype == 1: p_type = parted.PARTITION_LOGICAL elif ptype == 2: p_type = parted.PARTITION_EXTENDED else: p_type = parted.PARTITION_NORMAL geometry = parted.Geometry(start=start, end=end, device=self.device) if fstype and fstype not in bad_fs: filesystem = parted.FileSystem(type=fstype, geometry=geometry) partition = parted.Partition(disk=self.pdisk, type=p_type, fs=filesystem, geometry=geometry) else: partition = parted.Partition(disk=self.pdisk, type=p_type, geometry=geometry) # Set any flags needed. for flags in flags.split(','): if "boot" in flags: partition.setFlag(parted.PARTITION_BOOT) elif "lvm" in flags: partition.setFlag(parted.PARTITION_LVM) elif "swap" in flags: partition.setFlag(parted.PARTITION_SWAP) elif "raid" in flags: partition.setFlag(parted.PARTITION_RAID) elif "bios_grub" in flags: partition.setFlag(parted.PARTITION_BIOS_GRUB) elif "esp" in flags: partition.setFlag(parted.PARTITION_ESP) elif "prep" in flags: partition.setFlag(parted.PARTITION_PREP) self.pdisk.addPartition( partition, constraint=parted.Constraint(exactGeom=geometry)) self.pdisk.commit() # Catch any IOException then print a warning and skip it, normally it's # due to the device being active in some way lvm, md, etc. except IOException: self.log.exception("Caught an IOException, when running parted.") pass
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 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 run(self): global name_to_status if '/dev/sda' in self.mountpoint: name_to_status[self.namedport] = self.mountpoint + ": Refusing to operate on /dev/sda. Burner script error" return # refuse to run a burn thread on the root partition if not self.mountpoint.startswith('/dev/sd'): name_to_status[self.namedport] = self.mountpoint + ": Invalid mountpoint. Burning script error" sd = parted.getDevice(self.mountpoint) name_to_status[self.namedport] = self.mountpoint + ": Partitioning " + sd.model sd.clobber() sd_disk = parted.freshDisk(sd, 'msdos') geometry1 = parted.Geometry(start=disk.part1.start, end=disk.part1.end, device=sd) filesystem1 = parted.FileSystem(type=disk.part1.id, geometry=geometry1) partition1 = parted.Partition(disk=sd_disk, type=parted.PARTITION_NORMAL, fs=filesystem1, geometry=geometry1) sd_disk.addPartition(partition1, constraint=sd.optimalAlignedConstraint) sd_disk.commit() geometry2 = parted.Geometry(start=disk.part2.start, end=sd.length, device=sd) filesystem2 = parted.FileSystem(type=disk.part2.id, geometry=geometry2) partition2 = parted.Partition(disk=sd_disk, type=parted.PARTITION_NORMAL, fs=filesystem2, geometry=geometry2) sd_disk.addPartition(partition2, constraint=sd.optimalAlignedConstraint) sd_disk.commit() # set the disk identifier by blasting in the four bytes manually... with open(self.mountpoint, 'wb') as p: p.seek(0x1b8) p.write(struct.pack("<I", disk.partid)) #### PARTITION 1 COPY name_to_status[self.namedport] = self.mountpoint + ": Copying partition 1..." p = subprocess.Popen(["dd", "if=" + image_dir + "/part1.img", "of=" + self.mountpoint + "1", "bs=1M"], stderr=subprocess.PIPE) for lines in p.stderr: if 'copied' in lines.decode("utf-8"): name_to_status[self.namedport] = self.mountpoint + ": " + lines.decode("utf-8") p.wait() if p.returncode != 0: name_to_status[self.namedport] = self.mountpoint + " ERROR: " + lines.decode("utf-8") return time.sleep(3) ##### PARTITION 2 COPY name_to_status[self.namedport] = self.mountpoint + ": Copying partition 2..." p = subprocess.Popen(["dd", "if=" + image_dir + "/part2.ext4", "of=" + self.mountpoint + "2", "bs=1M"], stderr=subprocess.PIPE) for lines in p.stderr: if 'copied' in lines.decode("utf-8"): name_to_status[self.namedport] = self.mountpoint + ": " + lines.decode("utf-8") p.wait() if p.returncode != 0: name_to_status[self.namedport] = self.mountpoint + " ERROR: " + lines.decode("utf-8") return time.sleep(3) ##### FSCK PARTITION 2 -- allow a couple iterations to get a "clean" fsck returncode = 1 iters = 0 while returncode != 0 and iters < 4: name_to_status[self.namedport] = self.mountpoint + ": fsck partition 2..." p = subprocess.Popen(["e2fsck", "-y", "-f", self.mountpoint + "2"], stderr=subprocess.PIPE, stdout=subprocess.PIPE) for lines in p.stderr: name_to_status[self.namedport] = self.mountpoint + ": " + lines.decode("utf-8") p.wait() returncode = p.returncode iters = iters + 1 if iters >= 3: name_to_status[self.namedport] = self.mountpoint + " ERROR: " + lines.decode("utf-8") return ##### RESIZE PARTITION 2 name_to_status[self.namedport] = self.mountpoint + ": resize partition 2..." p = subprocess.Popen(["resize2fs", self.mountpoint + "2"], stderr=subprocess.PIPE, stdout=subprocess.PIPE) for lines in p.stderr: name_to_status[self.namedport] = self.mountpoint + ": " + lines.decode("utf-8") p.wait() if p.returncode != 0: name_to_status[self.namedport] = self.mountpoint + " ERROR: " + lines.decode("utf-8") return ##### SET BLKID PARTITION 2 -- actually, this can be done in the source image! #name_to_status[self.namedport] = self.mountpoint + ": set blkid partition 2..." #p = subprocess.Popen(["tune2fs", self.mountpoint + "2", "-U", disk.uuid], stderr=subprocess.PIPE, stdout=subprocess.PIPE) #for lines in p.stderr: # name_to_status[self.namedport] = self.mountpoint + ": " + lines.decode("utf-8") #p.wait() #if p.returncode != 0: # name_to_status[self.namedport] = self.mountpoint + " ERROR: " + lines.decode("utf-8") # return ##### SET PASS STATE name_to_status[self.namedport] = self.mountpoint + " FINISHED" return
def main(): parser = argparse.ArgumentParser() parser.add_argument('name', help='name of the disk image to create') parser.add_argument( '--path', help='path to folder containing rootfs to be copied into disk image', type=str, default='/tmp/multistrap') args = parser.parse_args() # determine size of rootfs folder result = subprocess.run('du --null -sm {}'.format(args.path).split(), check=True, stdout=subprocess.PIPE, encoding='UTF-8') rootsize = int(result.stdout.split() [0]) # numeric size is at the beginning of the output line print('Found rootfs folder at {} with size {} MB'.format( args.path, rootsize)) # create disk image file print('Creating empty disk image file...') imgpath = '/tmp/' + args.name image = open(imgpath, 'w') size = rootsize + bootsize + extraspace image.seek((size * 10**6) - 1) # subtract one to align to 512-byte sector image.write('a') image.close() # setup loop device print('Setting up loopback device...') result = subprocess.run('losetup -f --show {}'.format(imgpath).split(), check=True, stdout=subprocess.PIPE, encoding='UTF-8') devpath = result.stdout.strip( ) # output from losetup gives path to loopback device print("loopback device created at {}".format(devpath)) # partition disk image print('Partitioning disk image...') # create boot partition print('Creating boot partition...') device = parted.getDevice(devpath) disk = parted.freshDisk(device, 'gpt') bootPartSize = bootsize * 10**6 # boot partiton is 128MB # convert from bytes to sectors bootlen = int(bootPartSize / device.sectorSize) bootgeom = parted.Geometry(device=device, start=1, length=bootlen) bootfs = parted.FileSystem(type='fat32', geometry=bootgeom) bootpart = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=bootfs, geometry=bootgeom) bootpart.name = 'boot' disk.addPartition(partition=bootpart, constraint=device.optimalAlignedConstraint) disk.commit() # create root partition print('Creating root partition') rootgeom = disk.getFreeSpaceRegions()[-1] rootfs = parted.FileSystem(type='ext4', geometry=rootgeom) rootpart = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=rootfs, geometry=rootgeom) rootpart.name = 'Debian' disk.addPartition(partition=rootpart, constraint=device.optimalAlignedConstraint) disk.commit() # delete loop device and recreate with partitions print('Removing loopback device and recreating with partition support...') result = subprocess.run('losetup -d {}'.format(devpath).split()) result = subprocess.run('losetup -f --show -P {}'.format(imgpath).split(), check=True, stdout=subprocess.PIPE, encoding='UTF-8') devpath = result.stdout.strip( ) # output from losetup gives path to loopback device print("loopback device created at {}".format(devpath)) # format partitions print('Formatting partitions...') subprocess.run('mkfs.fat -F 32 {}p1'.format(devpath).split(), check=True) # format first partition to FAT32 subprocess.run('mkfs.ext4 {}p2'.format(devpath).split(), check=True) # format second parition to ext4 # mount filesystems and copy files # delete loop device print('Cleaning up loopback device...') result = subprocess.run('losetup -d {}'.format(devpath).split())
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 partitionParted(self): """Build partitions according to the partition spec. XXX roth -- hopefully the GPT labels specified here work correctly (that is, are ignored) on an msdos label """ constraint = self.partedDevice.optimalAlignedConstraint # default partition layout constraint devices = {} def _u2s(sz, u): """Convert to units of logical sectors.""" bsz = sz * u bsz = bsz + self.partedDevice.sectorSize - 1 return bsz / self.partedDevice.sectorSize def _align(spos): """Align this sector number.""" sz = self.partedDevice.sectorSize psz = self.partedDevice.physicalSectorSize if type(psz) != int: return spos if psz <= sz: return spos if (psz % sz) != 0: return spos if psz > 1048576: return spos stride = psz / sz off = spos % stride off = stride - off off = off % stride spos += off return spos UNITS = { 'GiB' : 1024 * 1024 * 1024, 'G' : 1000 * 1000 * 1000, 'MiB' : 1024 * 1024, 'M' : 1000 * 1000, 'KiB' : 1024, 'K' : 1000, } for part in self.im.platformConf['installer']: label, partData = list(part.items())[0] if type(partData) == dict: sz, fmt = partData['='], partData.get('format', 'ext4') else: sz, fmt = partData, 'ext4' cnt = None nextBlock = self.nextBlock or 1 minpart = self.minpart or 1 for ul, ub in UNITS.items(): if sz.endswith(ul): cnt = _u2s(int(sz[:-len(ul)], 10), ub) break if sz == '100%': cnt = self.partedDevice.getLength() - nextBlock if cnt is None: self.log.error("invalid size (no units) for %s: %s", part, sz) return 1 start = _align(nextBlock) end = start + cnt - 1 if end <= self.partedDevice.getLength(): self.log.info("Allocating %d sectors for %s", cnt, label) else: self.log.warn("%s: start sector %d, end sector %d, max %d", label, start, end, self.partedDevice.getLength()) self.log.error("invalid partition %s [%s] (too big)", label, sz) return 1 geom = parted.Geometry(device=self.partedDevice, start=start, length=end-start+1) fs = parted.FileSystem(type=fmt, geometry=geom) part = parted.Partition(disk=self.partedDisk, type=parted.PARTITION_NORMAL, fs=fs, geometry=geom) if self.partedDisk.type == 'gpt': part.getPedPartition().set_name(label) self.partedDisk.addPartition(part, constraint=constraint) self.partedDisk.commit() self.check_call(('partprobe', self.device,)) if fmt == 'raw': self.log.info("Leaving %s (%s) unformatted (raw)", part.path, label) else: self.log.info("Formatting %s (%s) as %s", part.path, label, fmt) if fmt == 'msdos': self.mkdosfs(part.path, label=label) elif fmt == 'ext4': self.mke4fs(part.path, label=label, huge_file=False) elif fmt == 'ext2': self.mke2fs(part.path, label=label) else: self.mkfs(part.path, fstype=fmt) self.nextBlock, self.minpart = end+1, minpart+1 devices[label] = part.path if label == 'ONL-CONFIG' and self.configArchive is not None: self.restoreConfig(part.path) self.blkidParts = BlkidParser(log=self.log.getChild("blkid")) # re-read the partitions return 0
for d in dsks: free=dsks_free[d] if free < sizeperdisk: print "Please add {0:10.2} MiB to disk {1}".format( float(sizeperdisk-free)/2**20,d) toGrow+=1 if toGrow>0: exit(1) #Voeg evt partities toe for path, dsk in VG.disks.items(): if path in dsks: if dsk.primaryPartitionCount = dsk.maxPrimaryPartitionCount: continue freeGeo=dsk.getFreeSpacePartitions()[-1].geometry if freeGeo.start >= dsk.getPrimaryPartitions()[-1].geometry.end: filesystem = parted.FileSystem(type='ext3', geometry=geometry) partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, fs=filesystem, geometry=freeGeo) disk.addPartition(partition=partition, constraint=dev.optimalAlignedConstraint) partition.setFlag(parted.PARTITION_LVM) disk.commit() subprocess.check_call(['pvcreate',partition.path],stdout=stdout, stderr=stderr) subprocess.check_call(['vgextend',options.VG,partition.path],stdout=stdout, stderr=stderr) #Opnieuw VG info inlezen. VGs=initVGs() VG=VGs[options.VG] LV=VG[options.LV] lastseg=LV[sorted(LV.keys())[-1]] dsks=[pseg.pv.disk.device.path for pseg in lastseg]