github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/common/storagecommon/volumes.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storagecommon 5 6 import ( 7 "github.com/juju/errors" 8 "gopkg.in/juju/names.v2" 9 10 "github.com/juju/juju/apiserver/params" 11 "github.com/juju/juju/environs/config" 12 "github.com/juju/juju/state" 13 "github.com/juju/juju/storage" 14 "github.com/juju/juju/storage/poolmanager" 15 ) 16 17 // VolumeParams returns the parameters for creating or destroying 18 // the given volume. 19 func VolumeParams( 20 v state.Volume, 21 storageInstance state.StorageInstance, 22 modelUUID, controllerUUID string, 23 environConfig *config.Config, 24 poolManager poolmanager.PoolManager, 25 registry storage.ProviderRegistry, 26 ) (params.VolumeParams, error) { 27 28 var pool string 29 var size uint64 30 if stateVolumeParams, ok := v.Params(); ok { 31 pool = stateVolumeParams.Pool 32 size = stateVolumeParams.Size 33 } else { 34 volumeInfo, err := v.Info() 35 if err != nil { 36 return params.VolumeParams{}, errors.Trace(err) 37 } 38 pool = volumeInfo.Pool 39 size = volumeInfo.Size 40 } 41 42 volumeTags, err := StorageTags(storageInstance, modelUUID, controllerUUID, environConfig) 43 if err != nil { 44 return params.VolumeParams{}, errors.Annotate(err, "computing storage tags") 45 } 46 47 providerType, cfg, err := StoragePoolConfig(pool, poolManager, registry) 48 if err != nil { 49 return params.VolumeParams{}, errors.Trace(err) 50 } 51 return params.VolumeParams{ 52 v.Tag().String(), 53 size, 54 string(providerType), 55 cfg.Attrs(), 56 volumeTags, 57 nil, // attachment params set by the caller 58 }, nil 59 } 60 61 // StoragePoolConfig returns the storage provider type and 62 // configuration for a named storage pool. If there is no 63 // such pool with the specified name, but it identifies a 64 // storage provider, then that type will be returned with a 65 // nil configuration. 66 func StoragePoolConfig(name string, poolManager poolmanager.PoolManager, registry storage.ProviderRegistry) (storage.ProviderType, *storage.Config, error) { 67 pool, err := poolManager.Get(name) 68 if errors.IsNotFound(err) { 69 // If not a storage pool, then maybe a provider type. 70 providerType := storage.ProviderType(name) 71 if _, err1 := registry.StorageProvider(providerType); err1 != nil { 72 return "", nil, errors.Trace(err) 73 } 74 return providerType, &storage.Config{}, nil 75 } else if err != nil { 76 return "", nil, errors.Annotatef(err, "getting pool %q", name) 77 } 78 return pool.Provider(), pool, nil 79 } 80 81 // VolumesToState converts a slice of params.Volume to a mapping 82 // of volume tags to state.VolumeInfo. 83 func VolumesToState(in []params.Volume) (map[names.VolumeTag]state.VolumeInfo, error) { 84 m := make(map[names.VolumeTag]state.VolumeInfo) 85 for _, v := range in { 86 tag, volumeInfo, err := VolumeToState(v) 87 if err != nil { 88 return nil, errors.Trace(err) 89 } 90 m[tag] = volumeInfo 91 } 92 return m, nil 93 } 94 95 // VolumeToState converts a params.Volume to state.VolumeInfo 96 // and names.VolumeTag. 97 func VolumeToState(v params.Volume) (names.VolumeTag, state.VolumeInfo, error) { 98 if v.VolumeTag == "" { 99 return names.VolumeTag{}, state.VolumeInfo{}, errors.New("Tag is empty") 100 } 101 volumeTag, err := names.ParseVolumeTag(v.VolumeTag) 102 if err != nil { 103 return names.VolumeTag{}, state.VolumeInfo{}, errors.Trace(err) 104 } 105 return volumeTag, state.VolumeInfo{ 106 v.Info.HardwareId, 107 v.Info.WWN, 108 v.Info.Size, 109 "", // pool is set by state 110 v.Info.VolumeId, 111 v.Info.Persistent, 112 }, nil 113 } 114 115 // VolumeFromState converts a state.Volume to params.Volume. 116 func VolumeFromState(v state.Volume) (params.Volume, error) { 117 info, err := v.Info() 118 if err != nil { 119 return params.Volume{}, errors.Trace(err) 120 } 121 return params.Volume{ 122 v.VolumeTag().String(), 123 VolumeInfoFromState(info), 124 }, nil 125 } 126 127 // VolumeInfoFromState converts a state.VolumeInfo to params.VolumeInfo. 128 func VolumeInfoFromState(info state.VolumeInfo) params.VolumeInfo { 129 return params.VolumeInfo{ 130 info.VolumeId, 131 info.HardwareId, 132 info.WWN, 133 info.Pool, 134 info.Size, 135 info.Persistent, 136 } 137 } 138 139 // VolumeAttachmentPlanFromState converts a state.VolumeAttachmentPlan to params.VolumeAttachmentPlan. 140 func VolumeAttachmentPlanFromState(v state.VolumeAttachmentPlan) (params.VolumeAttachmentPlan, error) { 141 planInfo, err := v.PlanInfo() 142 if err != nil { 143 return params.VolumeAttachmentPlan{}, errors.Trace(err) 144 } 145 146 blockInfo, err := v.BlockDeviceInfo() 147 if err != nil { 148 if !errors.IsNotFound(err) { 149 return params.VolumeAttachmentPlan{}, errors.Trace(err) 150 } 151 } 152 return params.VolumeAttachmentPlan{ 153 VolumeTag: v.Volume().String(), 154 MachineTag: v.Machine().String(), 155 Life: params.Life(v.Life().String()), 156 PlanInfo: VolumeAttachmentPlanInfoFromState(planInfo), 157 BlockDevice: VolumeAttachmentPlanBlockInfoFromState(blockInfo), 158 }, nil 159 } 160 161 func VolumeAttachmentPlanBlockInfoFromState(blockInfo state.BlockDeviceInfo) storage.BlockDevice { 162 return storage.BlockDevice{ 163 DeviceName: blockInfo.DeviceName, 164 DeviceLinks: blockInfo.DeviceLinks, 165 Label: blockInfo.Label, 166 UUID: blockInfo.UUID, 167 HardwareId: blockInfo.HardwareId, 168 WWN: blockInfo.WWN, 169 BusAddress: blockInfo.BusAddress, 170 Size: blockInfo.Size, 171 FilesystemType: blockInfo.FilesystemType, 172 InUse: blockInfo.InUse, 173 MountPoint: blockInfo.MountPoint, 174 } 175 } 176 177 func VolumeAttachmentPlanInfoFromState(planInfo state.VolumeAttachmentPlanInfo) params.VolumeAttachmentPlanInfo { 178 return params.VolumeAttachmentPlanInfo{ 179 DeviceType: planInfo.DeviceType, 180 DeviceAttributes: planInfo.DeviceAttributes, 181 } 182 } 183 184 // VolumeAttachmentFromState converts a state.VolumeAttachment to params.VolumeAttachment. 185 func VolumeAttachmentFromState(v state.VolumeAttachment) (params.VolumeAttachment, error) { 186 info, err := v.Info() 187 if err != nil { 188 return params.VolumeAttachment{}, errors.Trace(err) 189 } 190 return params.VolumeAttachment{ 191 v.Volume().String(), 192 v.Host().String(), 193 VolumeAttachmentInfoFromState(info), 194 }, nil 195 } 196 197 // VolumeAttachmentInfoFromState converts a state.VolumeAttachmentInfo to params.VolumeAttachmentInfo. 198 func VolumeAttachmentInfoFromState(info state.VolumeAttachmentInfo) params.VolumeAttachmentInfo { 199 planInfo := ¶ms.VolumeAttachmentPlanInfo{} 200 if info.PlanInfo != nil { 201 planInfo.DeviceType = info.PlanInfo.DeviceType 202 planInfo.DeviceAttributes = info.PlanInfo.DeviceAttributes 203 } else { 204 planInfo = nil 205 } 206 return params.VolumeAttachmentInfo{ 207 info.DeviceName, 208 info.DeviceLink, 209 info.BusAddress, 210 info.ReadOnly, 211 planInfo, 212 } 213 } 214 215 // VolumeAttachmentInfosToState converts a map of volume tags to 216 // params.VolumeAttachmentInfo to a map of volume tags to 217 // state.VolumeAttachmentInfo. 218 func VolumeAttachmentInfosToState(in map[string]params.VolumeAttachmentInfo) (map[names.VolumeTag]state.VolumeAttachmentInfo, error) { 219 m := make(map[names.VolumeTag]state.VolumeAttachmentInfo) 220 for k, v := range in { 221 volumeTag, err := names.ParseVolumeTag(k) 222 if err != nil { 223 return nil, errors.Trace(err) 224 } 225 m[volumeTag] = VolumeAttachmentInfoToState(v) 226 } 227 return m, nil 228 } 229 230 func VolumeAttachmentPlanToState(in params.VolumeAttachmentPlan) (names.MachineTag, names.VolumeTag, state.VolumeAttachmentPlanInfo, state.BlockDeviceInfo, error) { 231 machineTag, err := names.ParseMachineTag(in.MachineTag) 232 if err != nil { 233 return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentPlanInfo{}, state.BlockDeviceInfo{}, err 234 } 235 volumeTag, err := names.ParseVolumeTag(in.VolumeTag) 236 if err != nil { 237 return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentPlanInfo{}, state.BlockDeviceInfo{}, err 238 } 239 info := VolumeAttachmentPlanInfoToState(in.PlanInfo) 240 blockInfo := BlockDeviceInfoToState(in.BlockDevice) 241 return machineTag, volumeTag, info, blockInfo, nil 242 } 243 244 func BlockDeviceInfoToState(in storage.BlockDevice) state.BlockDeviceInfo { 245 return state.BlockDeviceInfo{ 246 DeviceName: in.DeviceName, 247 DeviceLinks: in.DeviceLinks, 248 Label: in.Label, 249 UUID: in.UUID, 250 HardwareId: in.HardwareId, 251 WWN: in.WWN, 252 BusAddress: in.BusAddress, 253 Size: in.Size, 254 FilesystemType: in.FilesystemType, 255 InUse: in.InUse, 256 MountPoint: in.MountPoint, 257 } 258 } 259 260 // VolumeAttachmentToState converts a params.VolumeAttachment 261 // to a state.VolumeAttachmentInfo and tags. 262 func VolumeAttachmentToState(in params.VolumeAttachment) (names.MachineTag, names.VolumeTag, state.VolumeAttachmentInfo, error) { 263 machineTag, err := names.ParseMachineTag(in.MachineTag) 264 if err != nil { 265 return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentInfo{}, err 266 } 267 volumeTag, err := names.ParseVolumeTag(in.VolumeTag) 268 if err != nil { 269 return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentInfo{}, err 270 } 271 info := VolumeAttachmentInfoToState(in.Info) 272 return machineTag, volumeTag, info, nil 273 } 274 275 func VolumeAttachmentPlanInfoToState(in params.VolumeAttachmentPlanInfo) state.VolumeAttachmentPlanInfo { 276 deviceType := in.DeviceType 277 if deviceType == "" { 278 deviceType = storage.DeviceTypeLocal 279 } 280 281 return state.VolumeAttachmentPlanInfo{ 282 DeviceType: deviceType, 283 DeviceAttributes: in.DeviceAttributes, 284 } 285 } 286 287 // VolumeAttachmentInfoToState converts a params.VolumeAttachmentInfo 288 // to a state.VolumeAttachmentInfo. 289 func VolumeAttachmentInfoToState(in params.VolumeAttachmentInfo) state.VolumeAttachmentInfo { 290 planInfo := &state.VolumeAttachmentPlanInfo{} 291 if in.PlanInfo != nil { 292 planInfo.DeviceAttributes = in.PlanInfo.DeviceAttributes 293 planInfo.DeviceType = in.PlanInfo.DeviceType 294 } else { 295 planInfo = nil 296 } 297 return state.VolumeAttachmentInfo{ 298 in.DeviceName, 299 in.DeviceLink, 300 in.BusAddress, 301 in.ReadOnly, 302 planInfo, 303 } 304 } 305 306 // ParseVolumeAttachmentIds parses the strings, returning machine storage IDs. 307 func ParseVolumeAttachmentIds(stringIds []string) ([]params.MachineStorageId, error) { 308 ids := make([]params.MachineStorageId, len(stringIds)) 309 for i, s := range stringIds { 310 m, v, err := state.ParseVolumeAttachmentId(s) 311 if err != nil { 312 return nil, err 313 } 314 ids[i] = params.MachineStorageId{ 315 MachineTag: m.String(), 316 AttachmentTag: v.String(), 317 } 318 } 319 return ids, nil 320 }