Example #1
0
        /// <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);
        }