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