github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/api/storageprovisioner/provisioner.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storageprovisioner 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names" 9 10 "github.com/juju/juju/api/base" 11 "github.com/juju/juju/api/common" 12 apiwatcher "github.com/juju/juju/api/watcher" 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/watcher" 15 ) 16 17 const storageProvisionerFacade = "StorageProvisioner" 18 19 // State provides access to a storageprovisioner's view of the state. 20 type State struct { 21 facade base.FacadeCaller 22 scope names.Tag 23 24 *common.ModelWatcher 25 } 26 27 // NewState creates a new client-side StorageProvisioner facade. 28 func NewState(caller base.APICaller, scope names.Tag) (*State, error) { 29 switch scope.(type) { 30 case names.ModelTag: 31 case names.MachineTag: 32 default: 33 return nil, errors.Errorf("expected ModelTag or MachineTag, got %T", scope) 34 } 35 facadeCaller := base.NewFacadeCaller(caller, storageProvisionerFacade) 36 return &State{ 37 facadeCaller, 38 scope, 39 common.NewModelWatcher(facadeCaller), 40 }, nil 41 } 42 43 // WatchBlockDevices watches for changes to the specified machine's block devices. 44 func (st *State) WatchBlockDevices(m names.MachineTag) (watcher.NotifyWatcher, error) { 45 var results params.NotifyWatchResults 46 args := params.Entities{ 47 Entities: []params.Entity{{Tag: m.String()}}, 48 } 49 err := st.facade.FacadeCall("WatchBlockDevices", args, &results) 50 if err != nil { 51 return nil, err 52 } 53 if len(results.Results) != 1 { 54 panic(errors.Errorf("expected 1 result, got %d", len(results.Results))) 55 } 56 result := results.Results[0] 57 if result.Error != nil { 58 return nil, result.Error 59 } 60 w := apiwatcher.NewNotifyWatcher(st.facade.RawAPICaller(), result) 61 return w, nil 62 } 63 64 // WatchMachine watches for changes to the specified machine. 65 func (st *State) WatchMachine(m names.MachineTag) (watcher.NotifyWatcher, error) { 66 var results params.NotifyWatchResults 67 args := params.Entities{ 68 Entities: []params.Entity{{Tag: m.String()}}, 69 } 70 err := st.facade.FacadeCall("WatchMachines", args, &results) 71 if err != nil { 72 return nil, err 73 } 74 if len(results.Results) != 1 { 75 panic(errors.Errorf("expected 1 result, got %d", len(results.Results))) 76 } 77 result := results.Results[0] 78 if result.Error != nil { 79 return nil, result.Error 80 } 81 w := apiwatcher.NewNotifyWatcher(st.facade.RawAPICaller(), result) 82 return w, nil 83 } 84 85 // WatchVolumes watches for lifecycle changes to volumes scoped to the 86 // entity with the tag passed to NewState. 87 func (st *State) WatchVolumes() (watcher.StringsWatcher, error) { 88 return st.watchStorageEntities("WatchVolumes") 89 } 90 91 // WatchVolumes watches for lifecycle changes to volumes scoped to the 92 // entity with the tag passed to NewState. 93 func (st *State) WatchFilesystems() (watcher.StringsWatcher, error) { 94 return st.watchStorageEntities("WatchFilesystems") 95 } 96 97 func (st *State) watchStorageEntities(method string) (watcher.StringsWatcher, error) { 98 var results params.StringsWatchResults 99 args := params.Entities{ 100 Entities: []params.Entity{{Tag: st.scope.String()}}, 101 } 102 err := st.facade.FacadeCall(method, args, &results) 103 if err != nil { 104 return nil, err 105 } 106 if len(results.Results) != 1 { 107 panic(errors.Errorf("expected 1 result, got %d", len(results.Results))) 108 } 109 result := results.Results[0] 110 if result.Error != nil { 111 return nil, result.Error 112 } 113 w := apiwatcher.NewStringsWatcher(st.facade.RawAPICaller(), result) 114 return w, nil 115 } 116 117 // WatchVolumeAttachments watches for changes to volume attachments 118 // scoped to the entity with the tag passed to NewState. 119 func (st *State) WatchVolumeAttachments() (watcher.MachineStorageIdsWatcher, error) { 120 return st.watchAttachments("WatchVolumeAttachments", apiwatcher.NewVolumeAttachmentsWatcher) 121 } 122 123 // WatchFilesystemAttachments watches for changes to filesystem attachments 124 // scoped to the entity with the tag passed to NewState. 125 func (st *State) WatchFilesystemAttachments() (watcher.MachineStorageIdsWatcher, error) { 126 return st.watchAttachments("WatchFilesystemAttachments", apiwatcher.NewFilesystemAttachmentsWatcher) 127 } 128 129 func (st *State) watchAttachments( 130 method string, 131 newWatcher func(base.APICaller, params.MachineStorageIdsWatchResult) watcher.MachineStorageIdsWatcher, 132 ) (watcher.MachineStorageIdsWatcher, error) { 133 var results params.MachineStorageIdsWatchResults 134 args := params.Entities{ 135 Entities: []params.Entity{{Tag: st.scope.String()}}, 136 } 137 err := st.facade.FacadeCall(method, args, &results) 138 if err != nil { 139 return nil, err 140 } 141 if len(results.Results) != 1 { 142 panic(errors.Errorf("expected 1 result, got %d", len(results.Results))) 143 } 144 result := results.Results[0] 145 if result.Error != nil { 146 return nil, result.Error 147 } 148 w := newWatcher(st.facade.RawAPICaller(), result) 149 return w, nil 150 } 151 152 // Volumes returns details of volumes with the specified tags. 153 func (st *State) Volumes(tags []names.VolumeTag) ([]params.VolumeResult, error) { 154 args := params.Entities{ 155 Entities: make([]params.Entity, len(tags)), 156 } 157 for i, tag := range tags { 158 args.Entities[i].Tag = tag.String() 159 } 160 var results params.VolumeResults 161 err := st.facade.FacadeCall("Volumes", args, &results) 162 if err != nil { 163 return nil, err 164 } 165 if len(results.Results) != len(tags) { 166 panic(errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))) 167 } 168 return results.Results, nil 169 } 170 171 // Filesystems returns details of filesystems with the specified tags. 172 func (st *State) Filesystems(tags []names.FilesystemTag) ([]params.FilesystemResult, error) { 173 args := params.Entities{ 174 Entities: make([]params.Entity, len(tags)), 175 } 176 for i, tag := range tags { 177 args.Entities[i].Tag = tag.String() 178 } 179 var results params.FilesystemResults 180 err := st.facade.FacadeCall("Filesystems", args, &results) 181 if err != nil { 182 return nil, err 183 } 184 if len(results.Results) != len(tags) { 185 panic(errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))) 186 } 187 return results.Results, nil 188 } 189 190 // VolumeAttachments returns details of volume attachments with the specified IDs. 191 func (st *State) VolumeAttachments(ids []params.MachineStorageId) ([]params.VolumeAttachmentResult, error) { 192 args := params.MachineStorageIds{ids} 193 var results params.VolumeAttachmentResults 194 err := st.facade.FacadeCall("VolumeAttachments", args, &results) 195 if err != nil { 196 return nil, err 197 } 198 if len(results.Results) != len(ids) { 199 panic(errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))) 200 } 201 return results.Results, nil 202 } 203 204 // VolumeBlockDevices returns details of block devices corresponding to the volume 205 // attachments with the specified IDs. 206 func (st *State) VolumeBlockDevices(ids []params.MachineStorageId) ([]params.BlockDeviceResult, error) { 207 args := params.MachineStorageIds{ids} 208 var results params.BlockDeviceResults 209 err := st.facade.FacadeCall("VolumeBlockDevices", args, &results) 210 if err != nil { 211 return nil, err 212 } 213 if len(results.Results) != len(ids) { 214 panic(errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))) 215 } 216 return results.Results, nil 217 } 218 219 // FilesystemAttachments returns details of filesystem attachments with the specified IDs. 220 func (st *State) FilesystemAttachments(ids []params.MachineStorageId) ([]params.FilesystemAttachmentResult, error) { 221 args := params.MachineStorageIds{ids} 222 var results params.FilesystemAttachmentResults 223 err := st.facade.FacadeCall("FilesystemAttachments", args, &results) 224 if err != nil { 225 return nil, err 226 } 227 if len(results.Results) != len(ids) { 228 panic(errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))) 229 } 230 return results.Results, nil 231 } 232 233 // VolumeParams returns the parameters for creating the volumes 234 // with the specified tags. 235 func (st *State) VolumeParams(tags []names.VolumeTag) ([]params.VolumeParamsResult, error) { 236 args := params.Entities{ 237 Entities: make([]params.Entity, len(tags)), 238 } 239 for i, tag := range tags { 240 args.Entities[i].Tag = tag.String() 241 } 242 var results params.VolumeParamsResults 243 err := st.facade.FacadeCall("VolumeParams", args, &results) 244 if err != nil { 245 return nil, err 246 } 247 if len(results.Results) != len(tags) { 248 panic(errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))) 249 } 250 return results.Results, nil 251 } 252 253 // FilesystemParams returns the parameters for creating the filesystems 254 // with the specified tags. 255 func (st *State) FilesystemParams(tags []names.FilesystemTag) ([]params.FilesystemParamsResult, error) { 256 args := params.Entities{ 257 Entities: make([]params.Entity, len(tags)), 258 } 259 for i, tag := range tags { 260 args.Entities[i].Tag = tag.String() 261 } 262 var results params.FilesystemParamsResults 263 err := st.facade.FacadeCall("FilesystemParams", args, &results) 264 if err != nil { 265 return nil, err 266 } 267 if len(results.Results) != len(tags) { 268 panic(errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))) 269 } 270 return results.Results, nil 271 } 272 273 // VolumeAttachmentParams returns the parameters for creating the volume 274 // attachments with the specified tags. 275 func (st *State) VolumeAttachmentParams(ids []params.MachineStorageId) ([]params.VolumeAttachmentParamsResult, error) { 276 args := params.MachineStorageIds{ids} 277 var results params.VolumeAttachmentParamsResults 278 err := st.facade.FacadeCall("VolumeAttachmentParams", args, &results) 279 if err != nil { 280 return nil, err 281 } 282 if len(results.Results) != len(ids) { 283 panic(errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))) 284 } 285 return results.Results, nil 286 } 287 288 // FilesystemAttachmentParams returns the parameters for creating the 289 // filesystem attachments with the specified tags. 290 func (st *State) FilesystemAttachmentParams(ids []params.MachineStorageId) ([]params.FilesystemAttachmentParamsResult, error) { 291 args := params.MachineStorageIds{ids} 292 var results params.FilesystemAttachmentParamsResults 293 err := st.facade.FacadeCall("FilesystemAttachmentParams", args, &results) 294 if err != nil { 295 return nil, err 296 } 297 if len(results.Results) != len(ids) { 298 panic(errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))) 299 } 300 return results.Results, nil 301 } 302 303 // SetVolumeInfo records the details of newly provisioned volumes. 304 func (st *State) SetVolumeInfo(volumes []params.Volume) ([]params.ErrorResult, error) { 305 args := params.Volumes{Volumes: volumes} 306 var results params.ErrorResults 307 err := st.facade.FacadeCall("SetVolumeInfo", args, &results) 308 if err != nil { 309 return nil, err 310 } 311 if len(results.Results) != len(volumes) { 312 panic(errors.Errorf("expected %d result(s), got %d", len(volumes), len(results.Results))) 313 } 314 return results.Results, nil 315 } 316 317 // SetFilesystemInfo records the details of newly provisioned filesystems. 318 func (st *State) SetFilesystemInfo(filesystems []params.Filesystem) ([]params.ErrorResult, error) { 319 args := params.Filesystems{Filesystems: filesystems} 320 var results params.ErrorResults 321 err := st.facade.FacadeCall("SetFilesystemInfo", args, &results) 322 if err != nil { 323 return nil, err 324 } 325 if len(results.Results) != len(filesystems) { 326 panic(errors.Errorf("expected %d result(s), got %d", len(filesystems), len(results.Results))) 327 } 328 return results.Results, nil 329 } 330 331 // SetVolumeAttachmentInfo records the details of newly provisioned volume attachments. 332 func (st *State) SetVolumeAttachmentInfo(volumeAttachments []params.VolumeAttachment) ([]params.ErrorResult, error) { 333 args := params.VolumeAttachments{VolumeAttachments: volumeAttachments} 334 var results params.ErrorResults 335 err := st.facade.FacadeCall("SetVolumeAttachmentInfo", args, &results) 336 if err != nil { 337 return nil, err 338 } 339 if len(results.Results) != len(volumeAttachments) { 340 panic(errors.Errorf("expected %d result(s), got %d", len(volumeAttachments), len(results.Results))) 341 } 342 return results.Results, nil 343 } 344 345 // SetFilesystemAttachmentInfo records the details of newly provisioned filesystem attachments. 346 func (st *State) SetFilesystemAttachmentInfo(filesystemAttachments []params.FilesystemAttachment) ([]params.ErrorResult, error) { 347 args := params.FilesystemAttachments{FilesystemAttachments: filesystemAttachments} 348 var results params.ErrorResults 349 err := st.facade.FacadeCall("SetFilesystemAttachmentInfo", args, &results) 350 if err != nil { 351 return nil, err 352 } 353 if len(results.Results) != len(filesystemAttachments) { 354 panic(errors.Errorf("expected %d result(s), got %d", len(filesystemAttachments), len(results.Results))) 355 } 356 return results.Results, nil 357 } 358 359 // Life requests the life cycle of the entities with the specified tags. 360 func (st *State) Life(tags []names.Tag) ([]params.LifeResult, error) { 361 var results params.LifeResults 362 args := params.Entities{ 363 Entities: make([]params.Entity, len(tags)), 364 } 365 for i, tag := range tags { 366 args.Entities[i].Tag = tag.String() 367 } 368 if err := st.facade.FacadeCall("Life", args, &results); err != nil { 369 return nil, err 370 } 371 if len(results.Results) != len(tags) { 372 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 373 } 374 return results.Results, nil 375 } 376 377 // AttachmentLife requests the life cycle of the attachments with the specified IDs. 378 func (st *State) AttachmentLife(ids []params.MachineStorageId) ([]params.LifeResult, error) { 379 var results params.LifeResults 380 args := params.MachineStorageIds{ids} 381 if err := st.facade.FacadeCall("AttachmentLife", args, &results); err != nil { 382 return nil, err 383 } 384 if len(results.Results) != len(ids) { 385 return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results)) 386 } 387 return results.Results, nil 388 } 389 390 // EnsureDead progresses the entities with the specified tags to the Dead 391 // life cycle state, if they are Alive or Dying. 392 func (st *State) EnsureDead(tags []names.Tag) ([]params.ErrorResult, error) { 393 var results params.ErrorResults 394 args := params.Entities{ 395 Entities: make([]params.Entity, len(tags)), 396 } 397 for i, tag := range tags { 398 args.Entities[i].Tag = tag.String() 399 } 400 if err := st.facade.FacadeCall("EnsureDead", args, &results); err != nil { 401 return nil, err 402 } 403 if len(results.Results) != len(tags) { 404 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 405 } 406 return results.Results, nil 407 } 408 409 // Remove removes the entities with the specified tags from state. 410 func (st *State) Remove(tags []names.Tag) ([]params.ErrorResult, error) { 411 var results params.ErrorResults 412 args := params.Entities{ 413 Entities: make([]params.Entity, len(tags)), 414 } 415 for i, tag := range tags { 416 args.Entities[i].Tag = tag.String() 417 } 418 if err := st.facade.FacadeCall("Remove", args, &results); err != nil { 419 return nil, err 420 } 421 if len(results.Results) != len(tags) { 422 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 423 } 424 return results.Results, nil 425 } 426 427 // RemoveAttachments removes the attachments with the specified IDs from state. 428 func (st *State) RemoveAttachments(ids []params.MachineStorageId) ([]params.ErrorResult, error) { 429 var results params.ErrorResults 430 args := params.MachineStorageIds{ids} 431 if err := st.facade.FacadeCall("RemoveAttachment", args, &results); err != nil { 432 return nil, err 433 } 434 if len(results.Results) != len(ids) { 435 return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results)) 436 } 437 return results.Results, nil 438 } 439 440 // InstanceIds returns the provider specific instance ID for each machine, 441 // or an CodeNotProvisioned error if not set. 442 func (st *State) InstanceIds(tags []names.MachineTag) ([]params.StringResult, error) { 443 var results params.StringResults 444 args := params.Entities{ 445 Entities: make([]params.Entity, len(tags)), 446 } 447 for i, tag := range tags { 448 args.Entities[i].Tag = tag.String() 449 } 450 err := st.facade.FacadeCall("InstanceId", args, &results) 451 if err != nil { 452 return nil, errors.Trace(err) 453 } 454 if len(results.Results) != 1 { 455 return nil, errors.Errorf("expected %d result(s), got %d", len(results.Results), len(tags)) 456 } 457 return results.Results, nil 458 } 459 460 // SetStatus sets the status of storage entities. 461 func (st *State) SetStatus(args []params.EntityStatusArgs) error { 462 var result params.ErrorResults 463 err := st.facade.FacadeCall("SetStatus", params.SetStatus{args}, &result) 464 if err != nil { 465 return err 466 } 467 return result.Combine() 468 }