/// <summary> /// Generates the partitioning layout used for the client when restoring an image. /// </summary> public ClientPartition GenerateClientSchema() { var activeCounter = _hdToGet; HdNumberToGet = _hdToGet; //Look for first active hd if (!_imageSchema.HardDrives[HdNumberToGet].Active) { while (activeCounter <= _imageSchema.HardDrives.Count()) { if (_imageSchema.HardDrives[activeCounter - 1].Active) { HdNumberToGet = activeCounter - 1; } activeCounter++; } } LbsByte = Convert.ToInt32(_imageSchema.HardDrives[HdNumberToGet].Lbs); //logical block size in bytes NewHdBlk = Convert.ToInt64(_newHdSize) / LbsByte; //size of client hard drive in block //Find the Boot partition if (_imageSchema.HardDrives[HdNumberToGet].Boot.Length > 0) { BootPart = _imageSchema.HardDrives[HdNumberToGet].Boot.Substring(_imageSchema.HardDrives[HdNumberToGet].Boot.Length - 1, 1); } if (!PrimaryAndExtendedPartitionLayout()) { return(null); } if (ExtendedPartitionHelper.HasLogical) { if (!LogicalPartitionLayout()) { return(null); } } if (VolumeGroupHelpers.Any()) { if (!LogicalVolumeLayout()) { return(null); } } //Order partitions based of block start PrimaryAndExtendedPartitions = PrimaryAndExtendedPartitions.OrderBy(part => part.Start, new CustomComparer()).ToList(); LogicalPartitions = LogicalPartitions.OrderBy(part => part.Start, new CustomComparer()).ToList(); return(this); }
private bool LogicalPartitionLayout() { // Try to resize logical to fit inside newly created extended var percentCounter = -.1; var upSizeLock = new Dictionary <string, long>(); var logicalPartLayoutVerified = false; while (!logicalPartLayoutVerified) { percentCounter += .1; var isError = false; LogicalPartitions.Clear(); double totalExtendedPercentage = 0; var partCounter = -1; foreach (var part in _imageSchema.HardDrives[HdNumberToGet].Partitions) { partCounter++; if (part.Type.ToLower() != "logical") { continue; } var clientPartition = new ClientPartition { IsBoot = BootPart == part.Number, Number = part.Number, Start = part.Start, Type = part.Type, FsId = part.FsId, Uuid = part.Uuid, Guid = part.Guid, FsType = part.FsType }; var logicalPartitionHelper = new ServiceClientPartition(_imageProfile).Partition(HdNumberToGet, partCounter, _newHdSize); var percentOfExtendedForThisPartition = (double)logicalPartitionHelper.MinSizeBlk / ExtendedPartitionHelper.AgreedSizeBlk; var tmpClientPartitionSizeBlk = logicalPartitionHelper.MinSizeBlk; if (upSizeLock.ContainsKey(part.Number)) { tmpClientPartitionSizeBlk = upSizeLock[part.Number]; } else { if (logicalPartitionHelper.IsDynamicSize) { clientPartition.SizeIsDynamic = true; var percentOfOrigDrive = Convert.ToInt64(part.Size) / (double) Convert.ToInt64(_imageSchema.HardDrives[HdNumberToGet].Size); if (Convert.ToInt64(NewHdBlk * percentOfOrigDrive) < logicalPartitionHelper.MinSizeBlk) { //This will never work because each loop only gets smaller tmpClientPartitionSizeBlk = Convert.ToInt64(NewHdBlk * (percentOfOrigDrive + percentCounter / 100)); if (logicalPartitionHelper.MinSizeBlk < tmpClientPartitionSizeBlk) { upSizeLock.Add(part.Number, tmpClientPartitionSizeBlk); } } else { tmpClientPartitionSizeBlk = percentOfOrigDrive - percentCounter / 100 <= 0 ? Convert.ToInt64(NewHdBlk * percentOfOrigDrive) : Convert.ToInt64(NewHdBlk * (percentOfOrigDrive - percentCounter / 100)); percentOfExtendedForThisPartition = (double)tmpClientPartitionSizeBlk / ExtendedPartitionHelper.AgreedSizeBlk; } } } if (logicalPartitionHelper.MinSizeBlk > tmpClientPartitionSizeBlk) { isError = true; break; } totalExtendedPercentage += percentOfExtendedForThisPartition; clientPartition.Size = tmpClientPartitionSizeBlk; LogicalPartitions.Add(clientPartition); if (logicalPartitionHelper.PartitionHasVolumeGroup) { logicalPartitionHelper.VolumeGroupHelper.AgreedPvSizeBlk = tmpClientPartitionSizeBlk; VolumeGroupHelpers.Add(logicalPartitionHelper.VolumeGroupHelper); } } //Could not determine a partition layout that works with this hard drive if (isError && percentCounter > 99) { log.Error(JsonConvert.SerializeObject(PrimaryAndExtendedPartitions)); log.Error(JsonConvert.SerializeObject(LogicalPartitions)); return(false); } //This partition size doesn't work, continuation of break from earlier if (isError) { continue; } if (totalExtendedPercentage <= 1) { long totalAllocatedBlk = 0; var dynamicPartitionCount = 0; //If totalPercentage is too far below 1 try to increase size of available resizable partitions if (totalExtendedPercentage < .98) { foreach (var partition in LogicalPartitions) { totalAllocatedBlk += Convert.ToInt64(partition.Size); if (partition.SizeIsDynamic) { dynamicPartitionCount++; } } var totalUnallocated = ExtendedPartitionHelper.AgreedSizeBlk - totalAllocatedBlk; if (dynamicPartitionCount > 0) { foreach ( var partition in LogicalPartitions.Where(partition => partition.SizeIsDynamic)) { partition.Size = partition.Size + totalUnallocated / dynamicPartitionCount; } } } logicalPartLayoutVerified = true; } //Theoretically should never hit this, but added to prevent infinite loop if (percentCounter > 100) { return(false); } } return(true); }