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  }