/// <summary>
        ///     Calculates the minimum block size required for a single partition, taking into account any children partitions.
        /// </summary>
        public PartitionHelper Partition(int hdNumberToGet, int partNumberToGet, long newHdSize)
        {
            var partition = _imageSchema.HardDrives[hdNumberToGet].Partitions[partNumberToGet];
            var partitionHelper = new PartitionHelper { MinSizeBlk = 0 };
            var extendedPartitionHelper = new ExtendedPartitionHelper();
            if (partition.Type.ToLower() == "extended")
                extendedPartitionHelper = ExtendedPartition(hdNumberToGet, newHdSize);

            partitionHelper.VolumeGroupHelper = VolumeGroup(hdNumberToGet, partNumberToGet, newHdSize);
            var lbsByte = _imageSchema.HardDrives[hdNumberToGet].Lbs;
            var imagePath = Settings.PrimaryStoragePath + Path.DirectorySeparatorChar + "images" + Path.DirectorySeparatorChar + _imageProfile.Image.Name + Path.DirectorySeparatorChar + "hd" +
                           hdNumberToGet;

            //Look if any volume groups are present for this partition.  If so set the volumesize for the volume group to the minimum size
            //required for the volume group.  Volume groups are always treated as resizable even if none of the individual 
            //logical volumes are resizable
            if (partitionHelper.VolumeGroupHelper.Pv != null)
            {
                partitionHelper.PartitionHasVolumeGroup = true;
                partition.VolumeSize = (partitionHelper.VolumeGroupHelper.MinSizeBlk * lbsByte / 1024 / 1024);
            }


            if (partition.ForceFixedSize)
            {
                partitionHelper.MinSizeBlk = partition.Size;
                partitionHelper.IsDynamicSize = false;
            }
            //Use partition size that user has set for the partition, if it is set.
            else if (!string.IsNullOrEmpty(partition.CustomSize) && !string.IsNullOrEmpty(partition.CustomSizeUnit))
            {
                long customSizeBytes = 0;
                switch (partition.CustomSizeUnit)
                {
                    case "MB":
                        customSizeBytes = Convert.ToInt64(partition.CustomSize) * 1024 * 1024;
                        break;
                    case "GB":
                        customSizeBytes = Convert.ToInt64(partition.CustomSize) * 1024 * 1024 * 1024;
                        break;
                    case "%":
                        double hdPercent = Convert.ToDouble(partition.CustomSize) / 100;
                        customSizeBytes = Convert.ToInt64(hdPercent * newHdSize);
                        break;
                }
                partitionHelper.MinSizeBlk = customSizeBytes / lbsByte;
                partitionHelper.IsDynamicSize = false;
            }

            //If partition is not resizable.  Determine partition size.  Also if the partition is less than 5 gigs assume it is that
            // size for a reason, do not resize it even if it is marked as a resizable partition
            else if ((partition.VolumeSize == 0 && partition.Type.ToLower() != "extended") ||
                     (partition.Type.ToLower() == "extended" && extendedPartitionHelper.IsOnlySwap) ||
                     partition.Size * lbsByte <= 5368709120 || partition.FsType == "swap")
            {
                partitionHelper.MinSizeBlk = partition.Size;
                partitionHelper.IsDynamicSize = false;
            }
            //If resizable determine what percent of drive partition was originally and match that to the new drive
            //while making sure the min size is still less than the resized size.
            else
            {
                partitionHelper.IsDynamicSize = true;
                if (partition.Type.ToLower() == "extended")
                    partitionHelper.MinSizeBlk = extendedPartitionHelper.MinSizeBlk;
                else if (partitionHelper.VolumeGroupHelper.Pv != null)
                {
                    partitionHelper.MinSizeBlk = partitionHelper.VolumeGroupHelper.MinSizeBlk;
                }
                else
                {
                    string imageFile = null;
                    foreach (var ext in new[] { "ntfs", "fat", "extfs", "hfsp", "imager", "xfs" })
                    {
                        try
                        {
                            imageFile =
                                Directory.GetFiles(
                                    imagePath + Path.DirectorySeparatorChar,
                                    "part" + partition.Number + "." + ext + ".*")
                                    .FirstOrDefault();
                        }
                        catch (Exception ex)
                        {
                            Logger.Log(ex.Message);
                        }

                        if (imageFile != null) break;
                    }
                    if (Path.GetExtension(imageFile) == ".wim")
                        partitionHelper.MinSizeBlk = (partition.UsedMb * 1024 * 1024) / lbsByte;
                    else
                    {

                        //The resize value and used_mb value are calculated during upload by two different methods
                        //Use the one that is bigger just in case.
                        if (partition.VolumeSize > partition.UsedMb)
                            partitionHelper.MinSizeBlk = partition.VolumeSize * 1024 * 1024 / lbsByte;
                        else
                            partitionHelper.MinSizeBlk = (partition.UsedMb * 1024 * 1024) / lbsByte;
                    }
                }
            }

            return partitionHelper;
        }
        /// <summary>
        ///     Calculates the minimum block size for an extended partition by determining the minimum size of all logical
        ///     partitions that fall under the extended.  Does not assume that any extended partitions actually exist.
        /// </summary>
        public ExtendedPartitionHelper ExtendedPartition(int hdNumberToGet, long newHdSize)
        {
            var lbsByte = _imageSchema.HardDrives[hdNumberToGet].Lbs;
            var extendedPartitionHelper = new ExtendedPartitionHelper();

            //Determine if any Extended or Logical Partitions are present.  Needed ahead of time correctly calculate sizes.
            //And calculate minimum needed extended partition size

            bool schemaHasExtendedPartition = false;
            string logicalFsType = null;
            foreach (var part in _imageSchema.HardDrives[hdNumberToGet].Partitions.Where(part => part.Active))
            {
                if (part.Type.ToLower() == "extended")
                {
                    schemaHasExtendedPartition = true;
                }
                if (part.Type.ToLower() != "logical") continue;
                extendedPartitionHelper.LogicalCount++;
                logicalFsType = part.FsType;
                extendedPartitionHelper.HasLogical = true;
            }

            if (!schemaHasExtendedPartition) return extendedPartitionHelper;

            if (logicalFsType != null &&
                (extendedPartitionHelper.LogicalCount == 1 && logicalFsType.ToLower() == "swap"))
                extendedPartitionHelper.IsOnlySwap = true;

            var partitionCounter = -1;
            foreach (var partition in _imageSchema.HardDrives[hdNumberToGet].Partitions)
            {
                partitionCounter++;
                if (!partition.Active && partition.Type.ToLower() != "extended" && partition.Type.ToLower() != "logical")
                    continue;
                if (partition.Type.ToLower() == "extended")
                {
                    if (partition.ForceFixedSize)
                    {
                        extendedPartitionHelper.MinSizeBlk = partition.Size;                   
                        return extendedPartitionHelper;                       
                    }
                    if (!string.IsNullOrEmpty(partition.CustomSize) && !string.IsNullOrEmpty(partition.CustomSizeUnit))
                    {
                        long customSizeBytes = 0;
                        switch (partition.CustomSizeUnit)
                        {
                            case "MB":
                                customSizeBytes = Convert.ToInt64(partition.CustomSize) * 1024 * 1024;
                                break;
                            case "GB":
                                customSizeBytes = Convert.ToInt64(partition.CustomSize) * 1024 * 1024 * 1024;
                                break;
                            case "%":
                                double hdPercent = Convert.ToDouble(partition.CustomSize) / 100;
                                customSizeBytes = Convert.ToInt64(hdPercent * newHdSize);
                                break;
                        }
                        extendedPartitionHelper.MinSizeBlk = customSizeBytes / lbsByte;
                        return extendedPartitionHelper;         
                    }
                    //If Hd has extended but no logical, use the extended to calc size
                    if (!extendedPartitionHelper.HasLogical)
                    {
                        //In this case someone has defined an extended partition but has not created any logical
                        //This could just be for preperation of leaving room for more logical partition later
                        //This should be highly unlikely but should account for it anyway.  There is no way of knowing a minimum size required
                        //while still having the partition be resizable.  So will set minimum sized required to unless user overrides
                        //set arbitary minimum to 100MB
                        extendedPartitionHelper.MinSizeBlk = 100 * 1024 * 1024 / lbsByte;
                        return extendedPartitionHelper;         
                    }
                }

                else if (partition.Type.ToLower() == "logical")
                {
                    //Check if the logical partition is a physical volume for a volume group
                    if (partition.FsId.ToLower() == "8e" || partition.FsId.ToLower() == "8e00")
                    {
                        //Add to the minimum extended size the minimum size of the volume group
                        var volumeGroupHelper = VolumeGroup(hdNumberToGet, partitionCounter, newHdSize);
                        extendedPartitionHelper.MinSizeBlk += volumeGroupHelper.MinSizeBlk;

                        if (volumeGroupHelper.MinSizeBlk == 0)
                            extendedPartitionHelper.MinSizeBlk += partition.Size;
                    }
                    else
                    {
                        var partitionHelper = Partition(hdNumberToGet, partitionCounter, newHdSize);
                        extendedPartitionHelper.MinSizeBlk += partitionHelper.MinSizeBlk;
                    }
                }
            }

            //Logical paritions default to 1MB more than the previous block using fdisk. This needs to be added to extended size so logical parts will fit inside
            long epPadding = (((1048576/lbsByte)*extendedPartitionHelper.LogicalCount) + (1048576/lbsByte));
            extendedPartitionHelper.MinSizeBlk += epPadding;
            return extendedPartitionHelper;
        }