github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/pkg/os/device.go (about)

     1  package os
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"os"
     7  	"regexp"
     8  	"strconv"
     9  
    10  	"github.com/emc-advanced-dev/pkg/errors"
    11  )
    12  
    13  type DiskSize interface {
    14  	ToPartedFormat() string
    15  	ToBytes() Bytes
    16  }
    17  
    18  type Bytes int64
    19  
    20  func (s Bytes) ToPartedFormat() string {
    21  	return fmt.Sprintf("%dB", uint64(s))
    22  }
    23  
    24  func (s Bytes) ToBytes() Bytes {
    25  	return s
    26  }
    27  
    28  // ToMegaBytes returns lowest whole number of size_MB so that size_MB >= (size_B / 1024^2)
    29  func (s Bytes) ToMegaBytes() MegaBytes {
    30  	return MegaBytes(int(math.Ceil(float64(s) / float64(MegaBytes(1).ToBytes()))))
    31  }
    32  
    33  type MegaBytes int64
    34  
    35  func (s MegaBytes) ToPartedFormat() string {
    36  	return fmt.Sprintf("%dMiB", uint64(s))
    37  }
    38  
    39  func (s MegaBytes) ToBytes() Bytes {
    40  	return Bytes(s << 20)
    41  }
    42  
    43  type GigaBytes int64
    44  
    45  func (s GigaBytes) ToPartedFormat() string {
    46  	return fmt.Sprintf("%dGiB", uint64(s))
    47  }
    48  
    49  func (s GigaBytes) ToBytes() Bytes {
    50  	return Bytes(s << 30)
    51  }
    52  
    53  type Sectors int64
    54  
    55  const SectorSize = 512
    56  
    57  func (s Sectors) ToPartedFormat() string {
    58  	return fmt.Sprintf("%ds", uint64(s))
    59  }
    60  
    61  func (s Sectors) ToBytes() Bytes {
    62  	return Bytes(s * SectorSize)
    63  }
    64  
    65  func ToSectors(b DiskSize) (Sectors, error) {
    66  	inBytes := b.ToBytes()
    67  	if inBytes%SectorSize != 0 {
    68  		return 0, errors.New("can't convert to sectors", nil)
    69  	}
    70  	return Sectors(inBytes / SectorSize), nil
    71  }
    72  
    73  type BlockDevice string
    74  
    75  func (b BlockDevice) Name() string {
    76  	return string(b)
    77  }
    78  
    79  type Partitioner interface {
    80  	MakeTable() error
    81  	MakePart(partType string, start, size DiskSize) error
    82  }
    83  
    84  type Resource interface {
    85  	Acquire() (BlockDevice, error)
    86  	Release() error
    87  }
    88  
    89  type Part interface {
    90  	Resource
    91  
    92  	Size() DiskSize
    93  	Offset() DiskSize
    94  
    95  	Get() BlockDevice
    96  }
    97  
    98  func IsExists(f string) bool {
    99  	_, err := os.Stat(f)
   100  	return !os.IsNotExist(err)
   101  }
   102  
   103  // ParseSize parses disk size string (e.g. "10GB" or "150MB") into MegaBytes
   104  // If no unit string is provided, megabytes are assumed
   105  func ParseSize(sizeStr string) (MegaBytes, error) {
   106  	r, _ := regexp.Compile("^([0-9]+)(m|mb|M|MB|g|gb|G|GB)?$")
   107  	match := r.FindStringSubmatch(sizeStr)
   108  	if len(match) != 3 {
   109  		return -1, fmt.Errorf("%s: unrecognized size", sizeStr)
   110  	}
   111  	size, _ := strconv.ParseInt(match[1], 10, 64)
   112  	unit := match[2]
   113  	switch unit {
   114  	case "g", "gb", "G", "GB":
   115  		size *= 1024
   116  	}
   117  	if size == 0 {
   118  		return -1, fmt.Errorf("%s: size must be larger than zero", sizeStr)
   119  	}
   120  	return MegaBytes(size), nil
   121  }