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