def to_tgt(self, parent): '''Transfer the install profile information to tgt format''' if not self.modified(): part = deepcopy(self._tgt_part) else: # Something changed, need to create a new one geo = tgt.Geometry(parent.cylsz, self.blocksz) if self.type == PartitionInfo.UNUSED: # Partition was deleted. Return an empty partition, # which will indicate to target instantiation to # delete this partition return tgt.Partition(geo, self.number, PartitionInfo.DELETED, 0, 0, modified=True) offset = int(self.offset.size_as("b") / self.blocksz) offset = max(PartitionInfo.MIN_OFFSET, offset) blocks = self.get_blocks() if self.is_logical() or self.is_extended(): # Ensure that the required minimum amount of empty space # precedes and follows this logical partition offset += PartitionInfo.LOGICAL_BLOCK_PAD blocks -= 2 * PartitionInfo.LOGICAL_BLOCK_PAD # offset must be a multiple of tgt.Geometry.cylsz offset = round_to_multiple(offset, geo.cylsz) blocks = round_down(blocks, geo.cylsz) part = tgt.Partition(geo, self.number, self.id, offset, blocks, modified=True) part.use_whole = self.use_whole_segment child_list = () if not part.use_whole: slices = [] if self.boot_slice is not None: slices.append(self.boot_slice) if self.alt_slice is not None: slices.append(self.alt_slice) slices.extend(self.slices) for slice_info in slices: sl = slice_info.to_tgt(parent) if sl is not None: child_list += (sl, ) part.children = child_list return (part)
def to_tgt(self, parent): '''Transfer the install profile information to tgt format''' # Create tgt.Slice object if self.get_type() == SliceInfo.UNUSED: return None if not self.modified(): return self._tgt_slice # Don't need to include the 'backup' slice, libti will # automatically create one appropriately if self.number == SliceInfo.BACKUP_SLICE: return None # Something changed, need to create a new one geo = tgt.Geometry(parent.cylsz, self.blocksz) # offset must be a multiple of tgt.Geometry.cylsz off = int(self.offset.size_as("b") / self.blocksz) offset = round_to_multiple(off, geo.cylsz) blocks = round_to_multiple(self.get_blocks(), geo.cylsz) tag = tgt.Slice.UNASSIGNED slice_type = self.type[0] user = self.type[1] sl = tgt.Slice(geo, self.number, tag, slice_type, offset, blocks, modified=True, user=str(user), unmountable=self.unmountable, readonly=self.readonly) return (sl)
def get_recommended_size(): '''Returns the recommended size for the installation, in GB''' if DiskWindow.REC_SIZE is None: try: swap_dump = SwapDump() rec_size = str(get_rec_install_size(swap_dump)) + "mb" DiskWindow.REC_SIZE = DiskSpace(rec_size) rec_size = DiskWindow.REC_SIZE.size_as("gb") rec_size = round_to_multiple(rec_size, 0.1) DiskWindow.REC_SIZE.size = "%sgb" % rec_size except (InstallationError): logging.warn("Unable to determine recommended install size") DiskWindow.REC_SIZE = DiskSpace("10gb") return DiskWindow.REC_SIZE
def get_minimum_size(): '''Returns the minimum disk space needed for installation, in GB. The value returned from get_min_install_size is rounded up to the nearest tenth of a gigabyte, so that the UI ensures enough space is allocated, given that the UI only allows for precision to tenths of a gigabyte. ''' if DiskWindow.MIN_SIZE is None: try: swap_dump = SwapDump() min_size = str(get_min_install_size(swap_dump)) + "mb" DiskWindow.MIN_SIZE = DiskSpace(min_size) min_size = DiskWindow.MIN_SIZE.size_as("gb") min_size = round_to_multiple(min_size, 0.1) DiskWindow.MIN_SIZE.size = "%sgb" % min_size except (InstallationError): logging.warn("Unable to determine minimum install size") DiskWindow.MIN_SIZE = DiskSpace("6gb") return DiskWindow.MIN_SIZE
def to_tgt(self): '''Transfer the install profile information to tgt format ''' if self._tgt_disk is not None: tgt_disk = self._tgt_disk else: name = self.name blocks = round_to_multiple(self.get_blocks(), self.cylsz) controller = self.controller boot = self.boot removable = self.removable vendor = self.vendor serialno = self.serialno geo = tgt.Geometry(cylsz=self.cylsz, blocksz=self.blocksz) tgt_disk = tgt.Disk(geo, name, blocks, controller=controller, boot=boot, removable=removable, vendor=vendor, serialno=serialno) backup_slice = None if self.partitions: sl_iter = iter(self.get_solaris_data().slices) else: sl_iter = iter(self.slices) for slice_ in sl_iter: if slice_.number == SliceInfo.BACKUP_SLICE: backup_slice = slice_._tgt_slice break tgt_disk.use_whole = self.use_whole_segment child_list = () if not tgt_disk.use_whole: for partition in self.partitions: part = partition.to_tgt(self) if part is not None: child_list += (part,) tgt_disk.fdisk = True if not child_list: for slice_info in self.slices: sl = slice_info.to_tgt(self) if sl is not None: child_list += (sl,) tgt_disk.vtoc = True tgt_disk.children = child_list slice_parent = tgt_disk if child_list and isinstance(child_list[0], tgt.Partition): standards = [] logicals = [] ext_part = None for child in child_list: if child.id == PartitionInfo.DELETED: continue if child.number > PartitionInfo.MAX_STANDARD_PARTITIONS: logicals.append(child) else: standards.append(child) if child.id in PartitionInfo.EXTENDED: ext_part = child if child.id == PartitionInfo.SOLARIS: slice_parent = child adjust_tgt_parts(standards, tgt_parent=tgt_disk) if logicals: adjust_tgt_parts(logicals, ext_part=ext_part) slices = [] for child in slice_parent.children: if child.number == SliceInfo.BACKUP_SLICE: continue slices.append(child) if backup_slice is not None: slice_parent = backup_slice adjust_tgt_parts(slices, tgt_parent=slice_parent) # print out the tgt_disk object for debugging logging.debug("%s", tgt_disk) return tgt_disk
def adjust_tgt_parts(tgt_objs, tgt_parent=None, ext_part=None): '''Modify a list of tgt.Partitions or tgt.Slices in place. For each item in the list, ensure that its offset is *past* the previous tgt object, and ensure that its size + offset doesn't cause it to overlap with the subsequent partition/slice. tgt.Partitions/Slices whose 'modified' flag is false are ignored. These are assumed to already exist on the disk (and assumed to not overlap); new Partitions/Slices are adjusted around the existing ones. tgt_objs: A list of tgt.Partitions or tgt.Slices. Logical partitions should NOT be mixed with standard partitions. tgt_parent: The tgt.Disk or tgt.Partition on which the tgt_objs are supposed to fit ext_part: The extended partition on which the tgt_objs are supposed to fit It is invalid to specify both tgt_parent and ext_part (ext_part will be ignored and the resulting disk layout could be indeterminate) ''' if not tgt_objs: return if tgt_parent is not None: cylsz = tgt_parent.geometry.cylsz if isinstance(tgt_objs[0], tgt.Slice): # Checking slices on a partition/disk # Can start at 0 min_offset = 0 if isinstance(tgt_parent, tgt.Slice): # Using S2 to determine max. All blocks usable abs_max_end = tgt_parent.blocks else: # Using a disk or partition to determine max # Must leave 2 cylinders worth of space available abs_max_end = tgt_parent.blocks - 2 * cylsz else: # Checking partitions on a disk # Use the minimum partition offset as starting point # Don't exceed the end of the disk min_offset = PartitionInfo.MIN_OFFSET abs_max_end = tgt_parent.blocks elif ext_part is not None: # Logicals on an extended partition # Should have an offset past the start of the extended partition # Should not go past the end of the extended partition min_offset = ext_part.offset abs_max_end = ext_part.offset + ext_part.blocks cylsz = ext_part.geometry.cylsz else: raise TypeError("Must specify ext_part or tgt_parent keyword arg") for idx, tgt_obj in enumerate(tgt_objs): if tgt_obj.modified and tgt_obj.offset < min_offset: tgt_obj.offset = round_to_multiple(min_offset, cylsz) if tgt_obj is tgt_objs[-1]: # Last item in the list - don't let this obj slide past the end # of the disk/partition max_end = abs_max_end else: # More items in the list - don't let this obj overlap with the # next item max_end = tgt_objs[idx+1].offset - 1 if tgt_obj.modified and tgt_obj.offset + tgt_obj.blocks > max_end: shift = (tgt_obj.offset + tgt_obj.blocks) - max_end new_blocks = tgt_obj.blocks - shift tgt_obj.blocks = round_down(new_blocks, cylsz) # Minimum offset for next obj should be past the end of this obj. # Preserve the current value of min_offset if it happens to be greater # than the end of this obj (for example, if this slice overlaps with, # and lies completely within, a prior slice) min_offset = max(min_offset, tgt_obj.offset + tgt_obj.blocks + 1)