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  }