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