github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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/core/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  }
    22  
    23  // NewState creates a new client-side StorageProvisioner facade.
    24  func NewState(caller base.APICaller) (*State, error) {
    25  	facadeCaller := base.NewFacadeCaller(caller, storageProvisionerFacade)
    26  	return &State{facadeCaller}, nil
    27  }
    28  
    29  // WatchApplications returns a StringsWatcher that notifies of
    30  // changes to the lifecycles of CAAS applications in the current model.
    31  func (st *State) WatchApplications() (watcher.StringsWatcher, error) {
    32  	var result params.StringsWatchResult
    33  	if err := st.facade.FacadeCall("WatchApplications", nil, &result); err != nil {
    34  		return nil, err
    35  	}
    36  	if err := result.Error; err != nil {
    37  		return nil, result.Error
    38  	}
    39  	w := apiwatcher.NewStringsWatcher(st.facade.RawAPICaller(), result)
    40  	return w, 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  		return nil, 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  		return nil, 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 specified tag.
    87  func (st *State) WatchVolumes(scope names.Tag) (watcher.StringsWatcher, error) {
    88  	return st.watchStorageEntities("WatchVolumes", scope)
    89  }
    90  
    91  // WatchVolumes watches for lifecycle changes to volumes scoped to the
    92  // entity with the specified tag.
    93  func (st *State) WatchFilesystems(scope names.Tag) (watcher.StringsWatcher, error) {
    94  	return st.watchStorageEntities("WatchFilesystems", scope)
    95  }
    96  
    97  func (st *State) watchStorageEntities(method string, scope names.Tag) (watcher.StringsWatcher, error) {
    98  	var results params.StringsWatchResults
    99  	args := params.Entities{
   100  		Entities: []params.Entity{{Tag: 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  		return nil, 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 specified tag.
   119  func (st *State) WatchVolumeAttachments(scope names.Tag) (watcher.MachineStorageIdsWatcher, error) {
   120  	return st.watchAttachments("WatchVolumeAttachments", scope, apiwatcher.NewVolumeAttachmentsWatcher)
   121  }
   122  
   123  // WatchVolumeAttachmentPlans watches for changes to volume attachments
   124  // scoped to the entity with the tag passed to NewState.
   125  func (st *State) WatchVolumeAttachmentPlans(scope names.Tag) (watcher.MachineStorageIdsWatcher, error) {
   126  	return st.watchAttachments("WatchVolumeAttachmentPlans", scope, apiwatcher.NewVolumeAttachmentPlansWatcher)
   127  }
   128  
   129  // WatchFilesystemAttachments watches for changes to filesystem attachments
   130  // scoped to the entity with the specified tag.
   131  func (st *State) WatchFilesystemAttachments(scope names.Tag) (watcher.MachineStorageIdsWatcher, error) {
   132  	return st.watchAttachments("WatchFilesystemAttachments", scope, apiwatcher.NewFilesystemAttachmentsWatcher)
   133  }
   134  
   135  func (st *State) watchAttachments(
   136  	method string,
   137  	scope names.Tag,
   138  	newWatcher func(base.APICaller, params.MachineStorageIdsWatchResult) watcher.MachineStorageIdsWatcher,
   139  ) (watcher.MachineStorageIdsWatcher, error) {
   140  	var results params.MachineStorageIdsWatchResults
   141  	args := params.Entities{
   142  		Entities: []params.Entity{{Tag: scope.String()}},
   143  	}
   144  	err := st.facade.FacadeCall(method, args, &results)
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  	if len(results.Results) != 1 {
   149  		return nil, errors.Errorf("expected 1 result, got %d", len(results.Results))
   150  	}
   151  	result := results.Results[0]
   152  	if result.Error != nil {
   153  		return nil, result.Error
   154  	}
   155  	w := newWatcher(st.facade.RawAPICaller(), result)
   156  	return w, nil
   157  }
   158  
   159  // Volumes returns details of volumes with the specified tags.
   160  func (st *State) Volumes(tags []names.VolumeTag) ([]params.VolumeResult, error) {
   161  	args := params.Entities{
   162  		Entities: make([]params.Entity, len(tags)),
   163  	}
   164  	for i, tag := range tags {
   165  		args.Entities[i].Tag = tag.String()
   166  	}
   167  	var results params.VolumeResults
   168  	err := st.facade.FacadeCall("Volumes", args, &results)
   169  	if err != nil {
   170  		return nil, err
   171  	}
   172  	if len(results.Results) != len(tags) {
   173  		return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))
   174  	}
   175  	return results.Results, nil
   176  }
   177  
   178  // Filesystems returns details of filesystems with the specified tags.
   179  func (st *State) Filesystems(tags []names.FilesystemTag) ([]params.FilesystemResult, error) {
   180  	args := params.Entities{
   181  		Entities: make([]params.Entity, len(tags)),
   182  	}
   183  	for i, tag := range tags {
   184  		args.Entities[i].Tag = tag.String()
   185  	}
   186  	var results params.FilesystemResults
   187  	err := st.facade.FacadeCall("Filesystems", args, &results)
   188  	if err != nil {
   189  		return nil, err
   190  	}
   191  	if len(results.Results) != len(tags) {
   192  		return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))
   193  	}
   194  	return results.Results, nil
   195  }
   196  
   197  func (st *State) VolumeAttachmentPlans(ids []params.MachineStorageId) ([]params.VolumeAttachmentPlanResult, error) {
   198  	args := params.MachineStorageIds{ids}
   199  	var results params.VolumeAttachmentPlanResults
   200  	err := st.facade.FacadeCall("VolumeAttachmentPlans", args, &results)
   201  	if err != nil {
   202  		return nil, err
   203  	}
   204  	if len(results.Results) != len(ids) {
   205  		return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))
   206  	}
   207  	return results.Results, nil
   208  }
   209  
   210  func (st *State) RemoveVolumeAttachmentPlan(ids []params.MachineStorageId) ([]params.ErrorResult, error) {
   211  	var results params.ErrorResults
   212  	args := params.MachineStorageIds{
   213  		Ids: ids,
   214  	}
   215  	if err := st.facade.FacadeCall("RemoveVolumeAttachmentPlan", args, &results); err != nil {
   216  		return nil, err
   217  	}
   218  	return results.Results, nil
   219  }
   220  
   221  // VolumeAttachments returns details of volume attachments with the specified IDs.
   222  func (st *State) VolumeAttachments(ids []params.MachineStorageId) ([]params.VolumeAttachmentResult, error) {
   223  	args := params.MachineStorageIds{ids}
   224  	var results params.VolumeAttachmentResults
   225  	err := st.facade.FacadeCall("VolumeAttachments", args, &results)
   226  	if err != nil {
   227  		return nil, err
   228  	}
   229  	if len(results.Results) != len(ids) {
   230  		return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))
   231  	}
   232  	return results.Results, nil
   233  }
   234  
   235  // VolumeBlockDevices returns details of block devices corresponding to the volume
   236  // attachments with the specified IDs.
   237  func (st *State) VolumeBlockDevices(ids []params.MachineStorageId) ([]params.BlockDeviceResult, error) {
   238  	args := params.MachineStorageIds{ids}
   239  	var results params.BlockDeviceResults
   240  	err := st.facade.FacadeCall("VolumeBlockDevices", args, &results)
   241  	if err != nil {
   242  		return nil, err
   243  	}
   244  	if len(results.Results) != len(ids) {
   245  		return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))
   246  	}
   247  	return results.Results, nil
   248  }
   249  
   250  // FilesystemAttachments returns details of filesystem attachments with the specified IDs.
   251  func (st *State) FilesystemAttachments(ids []params.MachineStorageId) ([]params.FilesystemAttachmentResult, error) {
   252  	args := params.MachineStorageIds{ids}
   253  	var results params.FilesystemAttachmentResults
   254  	err := st.facade.FacadeCall("FilesystemAttachments", args, &results)
   255  	if err != nil {
   256  		return nil, err
   257  	}
   258  	if len(results.Results) != len(ids) {
   259  		return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))
   260  	}
   261  	return results.Results, nil
   262  }
   263  
   264  // VolumeParams returns the parameters for creating the volumes
   265  // with the specified tags.
   266  func (st *State) VolumeParams(tags []names.VolumeTag) ([]params.VolumeParamsResult, error) {
   267  	args := params.Entities{
   268  		Entities: make([]params.Entity, len(tags)),
   269  	}
   270  	for i, tag := range tags {
   271  		args.Entities[i].Tag = tag.String()
   272  	}
   273  	var results params.VolumeParamsResults
   274  	err := st.facade.FacadeCall("VolumeParams", args, &results)
   275  	if err != nil {
   276  		return nil, err
   277  	}
   278  	if len(results.Results) != len(tags) {
   279  		return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))
   280  	}
   281  	return results.Results, nil
   282  }
   283  
   284  // RemoveVolumeParams returns the parameters for destroying or releasing
   285  // the volumes with the specified tags.
   286  func (st *State) RemoveVolumeParams(tags []names.VolumeTag) ([]params.RemoveVolumeParamsResult, error) {
   287  	args := params.Entities{
   288  		Entities: make([]params.Entity, len(tags)),
   289  	}
   290  	for i, tag := range tags {
   291  		args.Entities[i].Tag = tag.String()
   292  	}
   293  	var results params.RemoveVolumeParamsResults
   294  	err := st.facade.FacadeCall("RemoveVolumeParams", args, &results)
   295  	if err != nil {
   296  		return nil, err
   297  	}
   298  	if len(results.Results) != len(tags) {
   299  		return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))
   300  	}
   301  	return results.Results, nil
   302  }
   303  
   304  // FilesystemParams returns the parameters for creating the filesystems
   305  // with the specified tags.
   306  func (st *State) FilesystemParams(tags []names.FilesystemTag) ([]params.FilesystemParamsResult, error) {
   307  	args := params.Entities{
   308  		Entities: make([]params.Entity, len(tags)),
   309  	}
   310  	for i, tag := range tags {
   311  		args.Entities[i].Tag = tag.String()
   312  	}
   313  	var results params.FilesystemParamsResults
   314  	err := st.facade.FacadeCall("FilesystemParams", args, &results)
   315  	if err != nil {
   316  		return nil, err
   317  	}
   318  	if len(results.Results) != len(tags) {
   319  		return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))
   320  	}
   321  	return results.Results, nil
   322  }
   323  
   324  // RemoveFilesystemParams returns the parameters for destroying or releasing
   325  // the filesystems with the specified tags.
   326  func (st *State) RemoveFilesystemParams(tags []names.FilesystemTag) ([]params.RemoveFilesystemParamsResult, error) {
   327  	args := params.Entities{
   328  		Entities: make([]params.Entity, len(tags)),
   329  	}
   330  	for i, tag := range tags {
   331  		args.Entities[i].Tag = tag.String()
   332  	}
   333  	var results params.RemoveFilesystemParamsResults
   334  	err := st.facade.FacadeCall("RemoveFilesystemParams", args, &results)
   335  	if err != nil {
   336  		return nil, err
   337  	}
   338  	if len(results.Results) != len(tags) {
   339  		return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))
   340  	}
   341  	return results.Results, nil
   342  }
   343  
   344  // VolumeAttachmentParams returns the parameters for creating the volume
   345  // attachments with the specified tags.
   346  func (st *State) VolumeAttachmentParams(ids []params.MachineStorageId) ([]params.VolumeAttachmentParamsResult, error) {
   347  	args := params.MachineStorageIds{ids}
   348  	var results params.VolumeAttachmentParamsResults
   349  	err := st.facade.FacadeCall("VolumeAttachmentParams", args, &results)
   350  	if err != nil {
   351  		return nil, err
   352  	}
   353  	if len(results.Results) != len(ids) {
   354  		return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))
   355  	}
   356  	return results.Results, nil
   357  }
   358  
   359  // FilesystemAttachmentParams returns the parameters for creating the
   360  // filesystem attachments with the specified tags.
   361  func (st *State) FilesystemAttachmentParams(ids []params.MachineStorageId) ([]params.FilesystemAttachmentParamsResult, error) {
   362  	args := params.MachineStorageIds{ids}
   363  	var results params.FilesystemAttachmentParamsResults
   364  	err := st.facade.FacadeCall("FilesystemAttachmentParams", args, &results)
   365  	if err != nil {
   366  		return nil, err
   367  	}
   368  	if len(results.Results) != len(ids) {
   369  		return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))
   370  	}
   371  	return results.Results, nil
   372  }
   373  
   374  // SetVolumeInfo records the details of newly provisioned volumes.
   375  func (st *State) SetVolumeInfo(volumes []params.Volume) ([]params.ErrorResult, error) {
   376  	args := params.Volumes{Volumes: volumes}
   377  	var results params.ErrorResults
   378  	err := st.facade.FacadeCall("SetVolumeInfo", args, &results)
   379  	if err != nil {
   380  		return nil, err
   381  	}
   382  	if len(results.Results) != len(volumes) {
   383  		return nil, errors.Errorf("expected %d result(s), got %d", len(volumes), len(results.Results))
   384  	}
   385  	return results.Results, nil
   386  }
   387  
   388  // SetFilesystemInfo records the details of newly provisioned filesystems.
   389  func (st *State) SetFilesystemInfo(filesystems []params.Filesystem) ([]params.ErrorResult, error) {
   390  	args := params.Filesystems{Filesystems: filesystems}
   391  	var results params.ErrorResults
   392  	err := st.facade.FacadeCall("SetFilesystemInfo", args, &results)
   393  	if err != nil {
   394  		return nil, err
   395  	}
   396  	if len(results.Results) != len(filesystems) {
   397  		return nil, errors.Errorf("expected %d result(s), got %d", len(filesystems), len(results.Results))
   398  	}
   399  	return results.Results, nil
   400  }
   401  
   402  func (st *State) CreateVolumeAttachmentPlans(volumeAttachmentPlans []params.VolumeAttachmentPlan) ([]params.ErrorResult, error) {
   403  	args := params.VolumeAttachmentPlans{VolumeAttachmentPlans: volumeAttachmentPlans}
   404  	var results params.ErrorResults
   405  	err := st.facade.FacadeCall("CreateVolumeAttachmentPlans", args, &results)
   406  	if err != nil {
   407  		return nil, err
   408  	}
   409  	if len(results.Results) != len(volumeAttachmentPlans) {
   410  		return nil, errors.Errorf("expected %d result(s), got %d", len(volumeAttachmentPlans), len(results.Results))
   411  	}
   412  	return results.Results, nil
   413  }
   414  
   415  func (st *State) SetVolumeAttachmentPlanBlockInfo(volumeAttachmentPlans []params.VolumeAttachmentPlan) ([]params.ErrorResult, error) {
   416  	args := params.VolumeAttachmentPlans{VolumeAttachmentPlans: volumeAttachmentPlans}
   417  	var results params.ErrorResults
   418  	err := st.facade.FacadeCall("SetVolumeAttachmentPlanBlockInfo", args, &results)
   419  	if err != nil {
   420  		return nil, err
   421  	}
   422  	if len(results.Results) != len(volumeAttachmentPlans) {
   423  		return nil, errors.Errorf("expected %d result(s), got %d", len(volumeAttachmentPlans), len(results.Results))
   424  	}
   425  	return results.Results, nil
   426  }
   427  
   428  // SetVolumeAttachmentInfo records the details of newly provisioned volume attachments.
   429  func (st *State) SetVolumeAttachmentInfo(volumeAttachments []params.VolumeAttachment) ([]params.ErrorResult, error) {
   430  	args := params.VolumeAttachments{VolumeAttachments: volumeAttachments}
   431  	var results params.ErrorResults
   432  	err := st.facade.FacadeCall("SetVolumeAttachmentInfo", args, &results)
   433  	if err != nil {
   434  		return nil, err
   435  	}
   436  	if len(results.Results) != len(volumeAttachments) {
   437  		return nil, errors.Errorf("expected %d result(s), got %d", len(volumeAttachments), len(results.Results))
   438  	}
   439  	return results.Results, nil
   440  }
   441  
   442  // SetFilesystemAttachmentInfo records the details of newly provisioned filesystem attachments.
   443  func (st *State) SetFilesystemAttachmentInfo(filesystemAttachments []params.FilesystemAttachment) ([]params.ErrorResult, error) {
   444  	args := params.FilesystemAttachments{FilesystemAttachments: filesystemAttachments}
   445  	var results params.ErrorResults
   446  	err := st.facade.FacadeCall("SetFilesystemAttachmentInfo", args, &results)
   447  	if err != nil {
   448  		return nil, err
   449  	}
   450  	if len(results.Results) != len(filesystemAttachments) {
   451  		return nil, errors.Errorf("expected %d result(s), got %d", len(filesystemAttachments), len(results.Results))
   452  	}
   453  	return results.Results, nil
   454  }
   455  
   456  // Life requests the life cycle of the entities with the specified tags.
   457  func (st *State) Life(tags []names.Tag) ([]params.LifeResult, error) {
   458  	var results params.LifeResults
   459  	args := params.Entities{
   460  		Entities: make([]params.Entity, len(tags)),
   461  	}
   462  	for i, tag := range tags {
   463  		args.Entities[i].Tag = tag.String()
   464  	}
   465  	if err := st.facade.FacadeCall("Life", args, &results); err != nil {
   466  		return nil, err
   467  	}
   468  	if len(results.Results) != len(tags) {
   469  		return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))
   470  	}
   471  	return results.Results, nil
   472  }
   473  
   474  // AttachmentLife requests the life cycle of the attachments with the specified IDs.
   475  func (st *State) AttachmentLife(ids []params.MachineStorageId) ([]params.LifeResult, error) {
   476  	var results params.LifeResults
   477  	args := params.MachineStorageIds{ids}
   478  	if err := st.facade.FacadeCall("AttachmentLife", args, &results); err != nil {
   479  		return nil, err
   480  	}
   481  	if len(results.Results) != len(ids) {
   482  		return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))
   483  	}
   484  	return results.Results, nil
   485  }
   486  
   487  // EnsureDead progresses the entities with the specified tags to the Dead
   488  // life cycle state, if they are Alive or Dying.
   489  func (st *State) EnsureDead(tags []names.Tag) ([]params.ErrorResult, error) {
   490  	var results params.ErrorResults
   491  	args := params.Entities{
   492  		Entities: make([]params.Entity, len(tags)),
   493  	}
   494  	for i, tag := range tags {
   495  		args.Entities[i].Tag = tag.String()
   496  	}
   497  	if err := st.facade.FacadeCall("EnsureDead", args, &results); err != nil {
   498  		return nil, err
   499  	}
   500  	if len(results.Results) != len(tags) {
   501  		return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))
   502  	}
   503  	return results.Results, nil
   504  }
   505  
   506  // Remove removes the entities with the specified tags from state.
   507  func (st *State) Remove(tags []names.Tag) ([]params.ErrorResult, error) {
   508  	var results params.ErrorResults
   509  	args := params.Entities{
   510  		Entities: make([]params.Entity, len(tags)),
   511  	}
   512  	for i, tag := range tags {
   513  		args.Entities[i].Tag = tag.String()
   514  	}
   515  	if err := st.facade.FacadeCall("Remove", args, &results); err != nil {
   516  		return nil, err
   517  	}
   518  	if len(results.Results) != len(tags) {
   519  		return nil, errors.Errorf("expected %d result(s), got %d", len(tags), len(results.Results))
   520  	}
   521  	return results.Results, nil
   522  }
   523  
   524  // RemoveAttachments removes the attachments with the specified IDs from state.
   525  func (st *State) RemoveAttachments(ids []params.MachineStorageId) ([]params.ErrorResult, error) {
   526  	var results params.ErrorResults
   527  	args := params.MachineStorageIds{ids}
   528  	if err := st.facade.FacadeCall("RemoveAttachment", args, &results); err != nil {
   529  		return nil, err
   530  	}
   531  	if len(results.Results) != len(ids) {
   532  		return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))
   533  	}
   534  	return results.Results, nil
   535  }
   536  
   537  // InstanceIds returns the provider specific instance ID for each machine,
   538  // or an CodeNotProvisioned error if not set.
   539  func (st *State) InstanceIds(tags []names.MachineTag) ([]params.StringResult, error) {
   540  	var results params.StringResults
   541  	args := params.Entities{
   542  		Entities: make([]params.Entity, len(tags)),
   543  	}
   544  	for i, tag := range tags {
   545  		args.Entities[i].Tag = tag.String()
   546  	}
   547  	err := st.facade.FacadeCall("InstanceId", args, &results)
   548  	if err != nil {
   549  		return nil, errors.Trace(err)
   550  	}
   551  	if len(results.Results) != 1 {
   552  		return nil, errors.Errorf("expected %d result(s), got %d", len(results.Results), len(tags))
   553  	}
   554  	return results.Results, nil
   555  }
   556  
   557  // SetStatus sets the status of storage entities.
   558  func (st *State) SetStatus(args []params.EntityStatusArgs) error {
   559  	var result params.ErrorResults
   560  	err := st.facade.FacadeCall("SetStatus", params.SetStatus{args}, &result)
   561  	if err != nil {
   562  		return err
   563  	}
   564  	return result.Combine()
   565  }