github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/provider/gce/google/disk.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package google 5 6 import ( 7 "github.com/juju/errors" 8 "google.golang.org/api/compute/v1" 9 ) 10 11 // The different types of disk persistence supported by GCE. 12 const ( 13 diskPersistenceTypeScratch = "SCRATCH" 14 diskPersistenceTypePersistent = "PERSISTENT" 15 ) 16 17 type DiskType string 18 19 // The types of disk supported by GCE 20 const ( 21 // persistent 22 DiskPersistentStandard DiskType = "pd-standard" 23 DiskPersistentSSD DiskType = "pd-ssd" 24 // scratch 25 DiskLocalSSD DiskType = "local-ssd" 26 ) 27 28 type DiskMode string 29 30 // The different disk modes supported by GCE. 31 const ( 32 ModeRW DiskMode = "READ_WRITE" 33 ModeRO DiskMode = "READ_ONLY" 34 ) 35 36 type DiskStatus string 37 38 const ( 39 StatusCreating DiskStatus = "CREATING" 40 StatusFailed DiskStatus = "FAILED" 41 StatusReady DiskStatus = "READY" 42 StatusRestoring DiskStatus = "RESTORING" 43 ) 44 45 // MinDiskSizeGB is the minimum/default size (in megabytes) for 46 // GCE disks. 47 // 48 // Note: GCE does not currently have an official minimum disk size. 49 // However, in testing we found the minimum size to be 10 GB due to 50 // the image size. See gceapi messsage. 51 // 52 // gceapi: Requested disk size cannot be smaller than the image size (10 GB) 53 const MinDiskSizeGB uint64 = 10 54 55 // gibToMib converts gibibytes to mebibytes. 56 func gibToMib(g int64) uint64 { 57 return uint64(g) * 1024 58 } 59 60 // DiskSpec holds all the data needed to request a new disk on GCE. 61 // Some fields are used only for attached disks (i.e. in association 62 // with instances). 63 type DiskSpec struct { 64 // SizeHintGB is the requested disk size in Gigabytes. It must be 65 // greater than 0. 66 SizeHintGB uint64 67 // ImageURL is the location of the image to which the disk should 68 // be initialized. 69 ImageURL string 70 // Boot indicates that this is a boot disk. An instance may only 71 // have one boot disk. (attached only) 72 Boot bool 73 // Scratch indicates that the disk should be a "scratch" disk 74 // instead of a "persistent" disk (the default). 75 Scratch bool 76 // Readonly indicates that the disk should not support writes. 77 Readonly bool 78 // AutoDelete indicates that the attached disk should be removed 79 // when the instance to which it is attached is removed. 80 AutoDelete bool 81 // PersistenDiskType is exclusive to persistent disks and indicates which of the 82 // persistent types available this disk should be. 83 PersistentDiskType DiskType 84 // Name: Name of the resource; provided by the client when the resource 85 // is created. The name must be 1-63 characters long, and comply with 86 // RFC1035. Specifically, the name must be 1-63 characters long and 87 // match the regular expression [a-z]([-a-z0-9]*[a-z0-9])? which means 88 // the first character must be a lowercase letter, and all following 89 // characters must be a dash, lowercase letter, or digit, except the 90 // last character, which cannot be a dash. 91 Name string 92 } 93 94 // TooSmall checks the spec's size hint and indicates whether or not 95 // it is smaller than the minimum disk size. 96 func (ds *DiskSpec) TooSmall() bool { 97 return ds.SizeHintGB < MinDiskSizeGB 98 } 99 100 // SizeGB returns the disk size to use for a new disk. The size hint 101 // is returned if it isn't too small (otherwise the min size is 102 // returned). 103 func (ds *DiskSpec) SizeGB() uint64 { 104 size := ds.SizeHintGB 105 if ds.TooSmall() { 106 size = MinDiskSizeGB 107 } 108 return size 109 } 110 111 // newAttached builds a compute.AttachedDisk using the information in 112 // the disk spec and returns it. 113 // 114 // Note: Not all AttachedDisk fields are set. 115 func (ds *DiskSpec) newAttached() *compute.AttachedDisk { 116 // TODO(ericsnow) Fail if SizeHintGB is 0? 117 diskType := diskPersistenceTypePersistent 118 if ds.Scratch { 119 diskType = diskPersistenceTypeScratch 120 } 121 mode := ModeRW 122 if ds.Readonly { 123 mode = ModeRO 124 } 125 126 disk := compute.AttachedDisk{ 127 Type: diskType, 128 Boot: ds.Boot, 129 Mode: string(mode), 130 AutoDelete: ds.AutoDelete, 131 InitializeParams: &compute.AttachedDiskInitializeParams{ 132 // DiskName (defaults to instance name) 133 DiskSizeGb: int64(ds.SizeGB()), 134 // DiskType (defaults to pd-standard, pd-ssd, local-ssd) 135 SourceImage: ds.ImageURL, 136 }, 137 // Interface (defaults to SCSI) 138 // DeviceName (GCE sets this, persistent disk only) 139 } 140 return &disk 141 } 142 143 // newDetached creates a new detached persistent disk representation, 144 // this DOES NOT create a disk in gce, just creates the spec. 145 // reference in https://cloud.google.com/compute/docs/reference/latest/disks#resource 146 func (ds *DiskSpec) newDetached() (*compute.Disk, error) { 147 if ds.Scratch { 148 return nil, errors.New("cannot create scratch volumes detached") 149 } 150 if ds.PersistentDiskType == DiskLocalSSD { 151 return nil, errors.New("cannot create local ssd disks detached") 152 } 153 return &compute.Disk{ 154 Name: ds.Name, 155 SizeGb: int64(ds.SizeGB()), 156 SourceImage: ds.ImageURL, 157 Type: string(ds.PersistentDiskType), 158 }, nil 159 } 160 161 // AttachedDisk represents a disk that is attached to an instance. 162 type AttachedDisk struct { 163 // VolumeName is the name of the volume that is attached, this is unique 164 // and used by gce as an identifier. 165 VolumeName string 166 // DeviceName is the name of the device in the instance, typycally 167 // is reflected into the /dev/disk/by-id/google-* 168 DeviceName string 169 // Mode is the read/write mode of the disk. 170 Mode DiskMode 171 } 172 173 // Disk represents a gce disk. 174 type Disk struct { 175 // Id is an unique identifier google adds to the disk, it usually 176 // is not used in the API. 177 Id uint64 178 // Name is a unique identifier string for each disk. 179 Name string 180 // Size is the size in mbit. 181 Size uint64 182 // Type is one of the available disk types supported by 183 // gce (persistent or ephemeral). 184 Type DiskType 185 // Zone indicates the zone in which the disk lives. 186 Zone string 187 // DiskStatus holds the status of he aforementioned disk. 188 Status DiskStatus 189 } 190 191 func NewDisk(cd *compute.Disk) *Disk { 192 d := &Disk{ 193 Id: cd.Id, 194 Name: cd.Name, 195 Size: gibToMib(cd.SizeGb), 196 Type: DiskType(cd.Type), 197 Zone: cd.Zone, 198 Status: DiskStatus(cd.Status), 199 } 200 return d 201 }