github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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 "gopkg.in/juju/names.v2" 9 10 "github.com/juju/juju/api/base" 11 apiwatcher "github.com/juju/juju/api/watcher" 12 "github.com/juju/juju/apiserver/params" 13 "github.com/juju/juju/core/watcher" 14 ) 15 16 const storageProvisionerFacade = "StorageProvisioner" 17 18 // State provides access to a storageprovisioner's view of the state. 19 type State struct { 20 facade base.FacadeCaller 21 } 22 23 // NewState creates a new client-side StorageProvisioner facade. 24 func NewState(caller base.APICaller) (*State, error) { 25 facadeCaller := base.NewFacadeCaller(caller, storageProvisionerFacade) 26 return &State{facadeCaller}, nil 27 } 28 29 // WatchApplications returns a StringsWatcher that notifies of 30 // changes to the lifecycles of CAAS applications in the current model. 31 func (st *State) WatchApplications() (watcher.StringsWatcher, error) { 32 var result params.StringsWatchResult 33 if err := st.facade.FacadeCall("WatchApplications", nil, &result); err != nil { 34 return nil, err 35 } 36 if err := result.Error; err != nil { 37 return nil, result.Error 38 } 39 w := apiwatcher.NewStringsWatcher(st.facade.RawAPICaller(), result) 40 return w, 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 return nil, 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 return nil, 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 specified tag. 87 func (st *State) WatchVolumes(scope names.Tag) (watcher.StringsWatcher, error) { 88 return st.watchStorageEntities("WatchVolumes", scope) 89 } 90 91 // WatchVolumes watches for lifecycle changes to volumes scoped to the 92 // entity with the specified tag. 93 func (st *State) WatchFilesystems(scope names.Tag) (watcher.StringsWatcher, error) { 94 return st.watchStorageEntities("WatchFilesystems", scope) 95 } 96 97 func (st *State) watchStorageEntities(method string, scope names.Tag) (watcher.StringsWatcher, error) { 98 var results params.StringsWatchResults 99 args := params.Entities{ 100 Entities: []params.Entity{{Tag: 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 return nil, 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 specified tag. 119 func (st *State) WatchVolumeAttachments(scope names.Tag) (watcher.MachineStorageIdsWatcher, error) { 120 return st.watchAttachments("WatchVolumeAttachments", scope, apiwatcher.NewVolumeAttachmentsWatcher) 121 } 122 123 // WatchVolumeAttachmentPlans watches for changes to volume attachments 124 // scoped to the entity with the tag passed to NewState. 125 func (st *State) WatchVolumeAttachmentPlans(scope names.Tag) (watcher.MachineStorageIdsWatcher, error) { 126 return st.watchAttachments("WatchVolumeAttachmentPlans", scope, apiwatcher.NewVolumeAttachmentPlansWatcher) 127 } 128 129 // WatchFilesystemAttachments watches for changes to filesystem attachments 130 // scoped to the entity with the specified tag. 131 func (st *State) WatchFilesystemAttachments(scope names.Tag) (watcher.MachineStorageIdsWatcher, error) { 132 return st.watchAttachments("WatchFilesystemAttachments", scope, apiwatcher.NewFilesystemAttachmentsWatcher) 133 } 134 135 func (st *State) watchAttachments( 136 method string, 137 scope names.Tag, 138 newWatcher func(base.APICaller, params.MachineStorageIdsWatchResult) watcher.MachineStorageIdsWatcher, 139 ) (watcher.MachineStorageIdsWatcher, error) { 140 var results params.MachineStorageIdsWatchResults 141 args := params.Entities{ 142 Entities: []params.Entity{{Tag: scope.String()}}, 143 } 144 err := st.facade.FacadeCall(method, args, &results) 145 if err != nil { 146 return nil, err 147 } 148 if len(results.Results) != 1 { 149 return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) 150 } 151 result := results.Results[0] 152 if result.Error != nil { 153 return nil, result.Error 154 } 155 w := newWatcher(st.facade.RawAPICaller(), result) 156 return w, nil 157 } 158 159 // Volumes returns details of volumes with the specified tags. 160 func (st *State) Volumes(tags []names.VolumeTag) ([]params.VolumeResult, error) { 161 args := params.Entities{ 162 Entities: make([]params.Entity, len(tags)), 163 } 164 for i, tag := range tags { 165 args.Entities[i].Tag = tag.String() 166 } 167 var results params.VolumeResults 168 err := st.facade.FacadeCall("Volumes", args, &results) 169 if err != nil { 170 return nil, err 171 } 172 if len(results.Results) != len(tags) { 173 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 174 } 175 return results.Results, nil 176 } 177 178 // Filesystems returns details of filesystems with the specified tags. 179 func (st *State) Filesystems(tags []names.FilesystemTag) ([]params.FilesystemResult, error) { 180 args := params.Entities{ 181 Entities: make([]params.Entity, len(tags)), 182 } 183 for i, tag := range tags { 184 args.Entities[i].Tag = tag.String() 185 } 186 var results params.FilesystemResults 187 err := st.facade.FacadeCall("Filesystems", args, &results) 188 if err != nil { 189 return nil, err 190 } 191 if len(results.Results) != len(tags) { 192 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 193 } 194 return results.Results, nil 195 } 196 197 func (st *State) VolumeAttachmentPlans(ids []params.MachineStorageId) ([]params.VolumeAttachmentPlanResult, error) { 198 args := params.MachineStorageIds{ids} 199 var results params.VolumeAttachmentPlanResults 200 err := st.facade.FacadeCall("VolumeAttachmentPlans", args, &results) 201 if err != nil { 202 return nil, err 203 } 204 if len(results.Results) != len(ids) { 205 return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results)) 206 } 207 return results.Results, nil 208 } 209 210 func (st *State) RemoveVolumeAttachmentPlan(ids []params.MachineStorageId) ([]params.ErrorResult, error) { 211 var results params.ErrorResults 212 args := params.MachineStorageIds{ 213 Ids: ids, 214 } 215 if err := st.facade.FacadeCall("RemoveVolumeAttachmentPlan", args, &results); err != nil { 216 return nil, err 217 } 218 return results.Results, nil 219 } 220 221 // VolumeAttachments returns details of volume attachments with the specified IDs. 222 func (st *State) VolumeAttachments(ids []params.MachineStorageId) ([]params.VolumeAttachmentResult, error) { 223 args := params.MachineStorageIds{ids} 224 var results params.VolumeAttachmentResults 225 err := st.facade.FacadeCall("VolumeAttachments", args, &results) 226 if err != nil { 227 return nil, err 228 } 229 if len(results.Results) != len(ids) { 230 return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results)) 231 } 232 return results.Results, nil 233 } 234 235 // VolumeBlockDevices returns details of block devices corresponding to the volume 236 // attachments with the specified IDs. 237 func (st *State) VolumeBlockDevices(ids []params.MachineStorageId) ([]params.BlockDeviceResult, error) { 238 args := params.MachineStorageIds{ids} 239 var results params.BlockDeviceResults 240 err := st.facade.FacadeCall("VolumeBlockDevices", args, &results) 241 if err != nil { 242 return nil, err 243 } 244 if len(results.Results) != len(ids) { 245 return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results)) 246 } 247 return results.Results, nil 248 } 249 250 // FilesystemAttachments returns details of filesystem attachments with the specified IDs. 251 func (st *State) FilesystemAttachments(ids []params.MachineStorageId) ([]params.FilesystemAttachmentResult, error) { 252 args := params.MachineStorageIds{ids} 253 var results params.FilesystemAttachmentResults 254 err := st.facade.FacadeCall("FilesystemAttachments", args, &results) 255 if err != nil { 256 return nil, err 257 } 258 if len(results.Results) != len(ids) { 259 return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results)) 260 } 261 return results.Results, nil 262 } 263 264 // VolumeParams returns the parameters for creating the volumes 265 // with the specified tags. 266 func (st *State) VolumeParams(tags []names.VolumeTag) ([]params.VolumeParamsResult, error) { 267 args := params.Entities{ 268 Entities: make([]params.Entity, len(tags)), 269 } 270 for i, tag := range tags { 271 args.Entities[i].Tag = tag.String() 272 } 273 var results params.VolumeParamsResults 274 err := st.facade.FacadeCall("VolumeParams", args, &results) 275 if err != nil { 276 return nil, err 277 } 278 if len(results.Results) != len(tags) { 279 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 280 } 281 return results.Results, nil 282 } 283 284 // RemoveVolumeParams returns the parameters for destroying or releasing 285 // the volumes with the specified tags. 286 func (st *State) RemoveVolumeParams(tags []names.VolumeTag) ([]params.RemoveVolumeParamsResult, error) { 287 args := params.Entities{ 288 Entities: make([]params.Entity, len(tags)), 289 } 290 for i, tag := range tags { 291 args.Entities[i].Tag = tag.String() 292 } 293 var results params.RemoveVolumeParamsResults 294 err := st.facade.FacadeCall("RemoveVolumeParams", args, &results) 295 if err != nil { 296 return nil, err 297 } 298 if len(results.Results) != len(tags) { 299 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 300 } 301 return results.Results, nil 302 } 303 304 // FilesystemParams returns the parameters for creating the filesystems 305 // with the specified tags. 306 func (st *State) FilesystemParams(tags []names.FilesystemTag) ([]params.FilesystemParamsResult, error) { 307 args := params.Entities{ 308 Entities: make([]params.Entity, len(tags)), 309 } 310 for i, tag := range tags { 311 args.Entities[i].Tag = tag.String() 312 } 313 var results params.FilesystemParamsResults 314 err := st.facade.FacadeCall("FilesystemParams", args, &results) 315 if err != nil { 316 return nil, err 317 } 318 if len(results.Results) != len(tags) { 319 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 320 } 321 return results.Results, nil 322 } 323 324 // RemoveFilesystemParams returns the parameters for destroying or releasing 325 // the filesystems with the specified tags. 326 func (st *State) RemoveFilesystemParams(tags []names.FilesystemTag) ([]params.RemoveFilesystemParamsResult, error) { 327 args := params.Entities{ 328 Entities: make([]params.Entity, len(tags)), 329 } 330 for i, tag := range tags { 331 args.Entities[i].Tag = tag.String() 332 } 333 var results params.RemoveFilesystemParamsResults 334 err := st.facade.FacadeCall("RemoveFilesystemParams", args, &results) 335 if err != nil { 336 return nil, err 337 } 338 if len(results.Results) != len(tags) { 339 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 340 } 341 return results.Results, nil 342 } 343 344 // VolumeAttachmentParams returns the parameters for creating the volume 345 // attachments with the specified tags. 346 func (st *State) VolumeAttachmentParams(ids []params.MachineStorageId) ([]params.VolumeAttachmentParamsResult, error) { 347 args := params.MachineStorageIds{ids} 348 var results params.VolumeAttachmentParamsResults 349 err := st.facade.FacadeCall("VolumeAttachmentParams", args, &results) 350 if err != nil { 351 return nil, err 352 } 353 if len(results.Results) != len(ids) { 354 return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results)) 355 } 356 return results.Results, nil 357 } 358 359 // FilesystemAttachmentParams returns the parameters for creating the 360 // filesystem attachments with the specified tags. 361 func (st *State) FilesystemAttachmentParams(ids []params.MachineStorageId) ([]params.FilesystemAttachmentParamsResult, error) { 362 args := params.MachineStorageIds{ids} 363 var results params.FilesystemAttachmentParamsResults 364 err := st.facade.FacadeCall("FilesystemAttachmentParams", args, &results) 365 if err != nil { 366 return nil, err 367 } 368 if len(results.Results) != len(ids) { 369 return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results)) 370 } 371 return results.Results, nil 372 } 373 374 // SetVolumeInfo records the details of newly provisioned volumes. 375 func (st *State) SetVolumeInfo(volumes []params.Volume) ([]params.ErrorResult, error) { 376 args := params.Volumes{Volumes: volumes} 377 var results params.ErrorResults 378 err := st.facade.FacadeCall("SetVolumeInfo", args, &results) 379 if err != nil { 380 return nil, err 381 } 382 if len(results.Results) != len(volumes) { 383 return nil, errors.Errorf("expected %d result(s), got %d", len(volumes), len(results.Results)) 384 } 385 return results.Results, nil 386 } 387 388 // SetFilesystemInfo records the details of newly provisioned filesystems. 389 func (st *State) SetFilesystemInfo(filesystems []params.Filesystem) ([]params.ErrorResult, error) { 390 args := params.Filesystems{Filesystems: filesystems} 391 var results params.ErrorResults 392 err := st.facade.FacadeCall("SetFilesystemInfo", args, &results) 393 if err != nil { 394 return nil, err 395 } 396 if len(results.Results) != len(filesystems) { 397 return nil, errors.Errorf("expected %d result(s), got %d", len(filesystems), len(results.Results)) 398 } 399 return results.Results, nil 400 } 401 402 func (st *State) CreateVolumeAttachmentPlans(volumeAttachmentPlans []params.VolumeAttachmentPlan) ([]params.ErrorResult, error) { 403 args := params.VolumeAttachmentPlans{VolumeAttachmentPlans: volumeAttachmentPlans} 404 var results params.ErrorResults 405 err := st.facade.FacadeCall("CreateVolumeAttachmentPlans", args, &results) 406 if err != nil { 407 return nil, err 408 } 409 if len(results.Results) != len(volumeAttachmentPlans) { 410 return nil, errors.Errorf("expected %d result(s), got %d", len(volumeAttachmentPlans), len(results.Results)) 411 } 412 return results.Results, nil 413 } 414 415 func (st *State) SetVolumeAttachmentPlanBlockInfo(volumeAttachmentPlans []params.VolumeAttachmentPlan) ([]params.ErrorResult, error) { 416 args := params.VolumeAttachmentPlans{VolumeAttachmentPlans: volumeAttachmentPlans} 417 var results params.ErrorResults 418 err := st.facade.FacadeCall("SetVolumeAttachmentPlanBlockInfo", args, &results) 419 if err != nil { 420 return nil, err 421 } 422 if len(results.Results) != len(volumeAttachmentPlans) { 423 return nil, errors.Errorf("expected %d result(s), got %d", len(volumeAttachmentPlans), len(results.Results)) 424 } 425 return results.Results, nil 426 } 427 428 // SetVolumeAttachmentInfo records the details of newly provisioned volume attachments. 429 func (st *State) SetVolumeAttachmentInfo(volumeAttachments []params.VolumeAttachment) ([]params.ErrorResult, error) { 430 args := params.VolumeAttachments{VolumeAttachments: volumeAttachments} 431 var results params.ErrorResults 432 err := st.facade.FacadeCall("SetVolumeAttachmentInfo", args, &results) 433 if err != nil { 434 return nil, err 435 } 436 if len(results.Results) != len(volumeAttachments) { 437 return nil, errors.Errorf("expected %d result(s), got %d", len(volumeAttachments), len(results.Results)) 438 } 439 return results.Results, nil 440 } 441 442 // SetFilesystemAttachmentInfo records the details of newly provisioned filesystem attachments. 443 func (st *State) SetFilesystemAttachmentInfo(filesystemAttachments []params.FilesystemAttachment) ([]params.ErrorResult, error) { 444 args := params.FilesystemAttachments{FilesystemAttachments: filesystemAttachments} 445 var results params.ErrorResults 446 err := st.facade.FacadeCall("SetFilesystemAttachmentInfo", args, &results) 447 if err != nil { 448 return nil, err 449 } 450 if len(results.Results) != len(filesystemAttachments) { 451 return nil, errors.Errorf("expected %d result(s), got %d", len(filesystemAttachments), len(results.Results)) 452 } 453 return results.Results, nil 454 } 455 456 // Life requests the life cycle of the entities with the specified tags. 457 func (st *State) Life(tags []names.Tag) ([]params.LifeResult, error) { 458 var results params.LifeResults 459 args := params.Entities{ 460 Entities: make([]params.Entity, len(tags)), 461 } 462 for i, tag := range tags { 463 args.Entities[i].Tag = tag.String() 464 } 465 if err := st.facade.FacadeCall("Life", args, &results); err != nil { 466 return nil, err 467 } 468 if len(results.Results) != len(tags) { 469 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 470 } 471 return results.Results, nil 472 } 473 474 // AttachmentLife requests the life cycle of the attachments with the specified IDs. 475 func (st *State) AttachmentLife(ids []params.MachineStorageId) ([]params.LifeResult, error) { 476 var results params.LifeResults 477 args := params.MachineStorageIds{ids} 478 if err := st.facade.FacadeCall("AttachmentLife", args, &results); err != nil { 479 return nil, err 480 } 481 if len(results.Results) != len(ids) { 482 return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results)) 483 } 484 return results.Results, nil 485 } 486 487 // EnsureDead progresses the entities with the specified tags to the Dead 488 // life cycle state, if they are Alive or Dying. 489 func (st *State) EnsureDead(tags []names.Tag) ([]params.ErrorResult, error) { 490 var results params.ErrorResults 491 args := params.Entities{ 492 Entities: make([]params.Entity, len(tags)), 493 } 494 for i, tag := range tags { 495 args.Entities[i].Tag = tag.String() 496 } 497 if err := st.facade.FacadeCall("EnsureDead", args, &results); err != nil { 498 return nil, err 499 } 500 if len(results.Results) != len(tags) { 501 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 502 } 503 return results.Results, nil 504 } 505 506 // Remove removes the entities with the specified tags from state. 507 func (st *State) Remove(tags []names.Tag) ([]params.ErrorResult, error) { 508 var results params.ErrorResults 509 args := params.Entities{ 510 Entities: make([]params.Entity, len(tags)), 511 } 512 for i, tag := range tags { 513 args.Entities[i].Tag = tag.String() 514 } 515 if err := st.facade.FacadeCall("Remove", args, &results); err != nil { 516 return nil, err 517 } 518 if len(results.Results) != len(tags) { 519 return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results)) 520 } 521 return results.Results, nil 522 } 523 524 // RemoveAttachments removes the attachments with the specified IDs from state. 525 func (st *State) RemoveAttachments(ids []params.MachineStorageId) ([]params.ErrorResult, error) { 526 var results params.ErrorResults 527 args := params.MachineStorageIds{ids} 528 if err := st.facade.FacadeCall("RemoveAttachment", args, &results); err != nil { 529 return nil, err 530 } 531 if len(results.Results) != len(ids) { 532 return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results)) 533 } 534 return results.Results, nil 535 } 536 537 // InstanceIds returns the provider specific instance ID for each machine, 538 // or an CodeNotProvisioned error if not set. 539 func (st *State) InstanceIds(tags []names.MachineTag) ([]params.StringResult, error) { 540 var results params.StringResults 541 args := params.Entities{ 542 Entities: make([]params.Entity, len(tags)), 543 } 544 for i, tag := range tags { 545 args.Entities[i].Tag = tag.String() 546 } 547 err := st.facade.FacadeCall("InstanceId", args, &results) 548 if err != nil { 549 return nil, errors.Trace(err) 550 } 551 if len(results.Results) != 1 { 552 return nil, errors.Errorf("expected %d result(s), got %d", len(results.Results), len(tags)) 553 } 554 return results.Results, nil 555 } 556 557 // SetStatus sets the status of storage entities. 558 func (st *State) SetStatus(args []params.EntityStatusArgs) error { 559 var result params.ErrorResults 560 err := st.facade.FacadeCall("SetStatus", params.SetStatus{args}, &result) 561 if err != nil { 562 return err 563 } 564 return result.Combine() 565 }