github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/apiserver/uniter/uniter_base.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // The uniter package implements the API interface used by the uniter
     5  // worker. This file contains code common to all API versions.
     6  package uniter
     7  
     8  import (
     9  	"fmt"
    10  	"net/url"
    11  	"path"
    12  	"time"
    13  
    14  	"github.com/juju/errors"
    15  	"github.com/juju/names"
    16  	"gopkg.in/juju/charm.v4"
    17  
    18  	"github.com/juju/juju/apiserver/common"
    19  	leadershipapiserver "github.com/juju/juju/apiserver/leadership"
    20  	"github.com/juju/juju/apiserver/params"
    21  	"github.com/juju/juju/leadership"
    22  	"github.com/juju/juju/lease"
    23  	"github.com/juju/juju/network"
    24  	"github.com/juju/juju/state"
    25  	"github.com/juju/juju/state/multiwatcher"
    26  	"github.com/juju/juju/state/watcher"
    27  )
    28  
    29  // uniterBaseAPI implements common methods used by all API versions,
    30  // and it's intended for embedding.
    31  type uniterBaseAPI struct {
    32  	*common.LifeGetter
    33  	*common.StatusSetter
    34  	*common.DeadEnsurer
    35  	*common.AgentEntityWatcher
    36  	*common.APIAddresser
    37  	*common.EnvironWatcher
    38  	*common.RebootRequester
    39  	*leadershipapiserver.LeadershipSettingsAccessor
    40  
    41  	st            *state.State
    42  	auth          common.Authorizer
    43  	resources     *common.Resources
    44  	accessUnit    common.GetAuthFunc
    45  	accessService common.GetAuthFunc
    46  	unit          *state.Unit
    47  }
    48  
    49  // newUniterBaseAPI creates a new instance of the uniter base API.
    50  func newUniterBaseAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*uniterBaseAPI, error) {
    51  	if !authorizer.AuthUnitAgent() {
    52  		return nil, common.ErrPerm
    53  	}
    54  	var unit *state.Unit
    55  	var err error
    56  	switch tag := authorizer.GetAuthTag().(type) {
    57  	case names.UnitTag:
    58  		unit, err = st.Unit(tag.Id())
    59  		if err != nil {
    60  			return nil, errors.Trace(err)
    61  		}
    62  	default:
    63  		return nil, errors.Errorf("expected names.UnitTag, got %T", tag)
    64  	}
    65  	accessUnit := func() (common.AuthFunc, error) {
    66  		return authorizer.AuthOwner, nil
    67  	}
    68  	accessService := func() (common.AuthFunc, error) {
    69  		switch tag := authorizer.GetAuthTag().(type) {
    70  		case names.UnitTag:
    71  			entity, err := st.Unit(tag.Id())
    72  			if err != nil {
    73  				return nil, errors.Trace(err)
    74  			}
    75  			serviceName := entity.ServiceName()
    76  			serviceTag := names.NewServiceTag(serviceName)
    77  			return func(tag names.Tag) bool {
    78  				return tag == serviceTag
    79  			}, nil
    80  		default:
    81  			return nil, errors.Errorf("expected names.UnitTag, got %T", tag)
    82  		}
    83  	}
    84  	accessMachine := func() (common.AuthFunc, error) {
    85  		machineId, err := unit.AssignedMachineId()
    86  		if err != nil {
    87  			return nil, errors.Trace(err)
    88  		}
    89  		machine, err := st.Machine(machineId)
    90  		if err != nil {
    91  			return nil, errors.Trace(err)
    92  		}
    93  		return func(tag names.Tag) bool {
    94  			return tag == machine.Tag()
    95  		}, nil
    96  	}
    97  
    98  	accessUnitOrService := common.AuthEither(accessUnit, accessService)
    99  	return &uniterBaseAPI{
   100  		LifeGetter:                 common.NewLifeGetter(st, accessUnitOrService),
   101  		StatusSetter:               common.NewStatusSetter(st, accessUnit),
   102  		DeadEnsurer:                common.NewDeadEnsurer(st, accessUnit),
   103  		AgentEntityWatcher:         common.NewAgentEntityWatcher(st, resources, accessUnitOrService),
   104  		APIAddresser:               common.NewAPIAddresser(st, resources),
   105  		EnvironWatcher:             common.NewEnvironWatcher(st, resources, authorizer),
   106  		RebootRequester:            common.NewRebootRequester(st, accessMachine),
   107  		LeadershipSettingsAccessor: leadershipSettingsAccessorFactory(st, resources, authorizer),
   108  
   109  		st:            st,
   110  		auth:          authorizer,
   111  		resources:     resources,
   112  		accessUnit:    accessUnit,
   113  		accessService: accessService,
   114  		unit:          unit,
   115  	}, nil
   116  }
   117  
   118  // PublicAddress returns the public address for each given unit, if set.
   119  func (u *uniterBaseAPI) PublicAddress(args params.Entities) (params.StringResults, error) {
   120  	result := params.StringResults{
   121  		Results: make([]params.StringResult, len(args.Entities)),
   122  	}
   123  	canAccess, err := u.accessUnit()
   124  	if err != nil {
   125  		return params.StringResults{}, err
   126  	}
   127  	for i, entity := range args.Entities {
   128  		tag, err := names.ParseUnitTag(entity.Tag)
   129  		if err != nil {
   130  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   131  			continue
   132  		}
   133  		err = common.ErrPerm
   134  		if canAccess(tag) {
   135  			var unit *state.Unit
   136  			unit, err = u.getUnit(tag)
   137  			if err == nil {
   138  				address, ok := unit.PublicAddress()
   139  				if ok {
   140  					result.Results[i].Result = address
   141  				} else {
   142  					err = common.NoAddressSetError(tag, "public")
   143  				}
   144  			}
   145  		}
   146  		result.Results[i].Error = common.ServerError(err)
   147  	}
   148  	return result, nil
   149  }
   150  
   151  // PrivateAddress returns the private address for each given unit, if set.
   152  func (u *uniterBaseAPI) PrivateAddress(args params.Entities) (params.StringResults, error) {
   153  	result := params.StringResults{
   154  		Results: make([]params.StringResult, len(args.Entities)),
   155  	}
   156  	canAccess, err := u.accessUnit()
   157  	if err != nil {
   158  		return params.StringResults{}, err
   159  	}
   160  	for i, entity := range args.Entities {
   161  		tag, err := names.ParseUnitTag(entity.Tag)
   162  		if err != nil {
   163  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   164  			continue
   165  		}
   166  		err = common.ErrPerm
   167  		if canAccess(tag) {
   168  			var unit *state.Unit
   169  			unit, err = u.getUnit(tag)
   170  			if err == nil {
   171  				address, ok := unit.PrivateAddress()
   172  				if ok {
   173  					result.Results[i].Result = address
   174  				} else {
   175  					err = common.NoAddressSetError(tag, "private")
   176  				}
   177  			}
   178  		}
   179  		result.Results[i].Error = common.ServerError(err)
   180  	}
   181  	return result, nil
   182  }
   183  
   184  // TODO(ericsnow) Factor out the common code amongst the many methods here.
   185  
   186  var getZone = func(st *state.State, tag names.Tag) (string, error) {
   187  	unit, err := st.Unit(tag.Id())
   188  	if err != nil {
   189  		return "", errors.Trace(err)
   190  	}
   191  	zone, err := unit.AvailabilityZone()
   192  	return zone, errors.Trace(err)
   193  }
   194  
   195  // AvailabilityZone returns the availability zone for each given unit, if applicable.
   196  func (u *uniterBaseAPI) AvailabilityZone(args params.Entities) (params.StringResults, error) {
   197  	var results params.StringResults
   198  
   199  	canAccess, err := u.accessUnit()
   200  	if err != nil {
   201  		return results, errors.Trace(err)
   202  	}
   203  
   204  	// Prep the results.
   205  	results = params.StringResults{
   206  		Results: make([]params.StringResult, len(args.Entities)),
   207  	}
   208  
   209  	// Collect the zones. No zone will be collected for any entity where
   210  	// the tag is invalid or not authorized. Instead the corresponding
   211  	// result will be updated with the error.
   212  	for i, entity := range args.Entities {
   213  		tag, err := names.ParseUnitTag(entity.Tag)
   214  		if err != nil {
   215  			results.Results[i].Error = common.ServerError(common.ErrPerm)
   216  			continue
   217  		}
   218  		err = common.ErrPerm
   219  		if canAccess(tag) {
   220  			var zone string
   221  			zone, err = getZone(u.st, tag)
   222  			if err == nil {
   223  				results.Results[i].Result = zone
   224  			}
   225  		}
   226  		results.Results[i].Error = common.ServerError(err)
   227  	}
   228  
   229  	return results, nil
   230  }
   231  
   232  // Resolved returns the current resolved setting for each given unit.
   233  func (u *uniterBaseAPI) Resolved(args params.Entities) (params.ResolvedModeResults, error) {
   234  	result := params.ResolvedModeResults{
   235  		Results: make([]params.ResolvedModeResult, len(args.Entities)),
   236  	}
   237  	canAccess, err := u.accessUnit()
   238  	if err != nil {
   239  		return params.ResolvedModeResults{}, err
   240  	}
   241  	for i, entity := range args.Entities {
   242  		tag, err := names.ParseUnitTag(entity.Tag)
   243  		if err != nil {
   244  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   245  			continue
   246  		}
   247  		err = common.ErrPerm
   248  		if canAccess(tag) {
   249  			var unit *state.Unit
   250  			unit, err = u.getUnit(tag)
   251  			if err == nil {
   252  				result.Results[i].Mode = params.ResolvedMode(unit.Resolved())
   253  			}
   254  		}
   255  		result.Results[i].Error = common.ServerError(err)
   256  	}
   257  	return result, nil
   258  }
   259  
   260  // ClearResolved removes any resolved setting from each given unit.
   261  func (u *uniterBaseAPI) ClearResolved(args params.Entities) (params.ErrorResults, error) {
   262  	result := params.ErrorResults{
   263  		Results: make([]params.ErrorResult, len(args.Entities)),
   264  	}
   265  	canAccess, err := u.accessUnit()
   266  	if err != nil {
   267  		return params.ErrorResults{}, err
   268  	}
   269  	for i, entity := range args.Entities {
   270  		tag, err := names.ParseUnitTag(entity.Tag)
   271  		if err != nil {
   272  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   273  			continue
   274  		}
   275  		err = common.ErrPerm
   276  		if canAccess(tag) {
   277  			var unit *state.Unit
   278  			unit, err = u.getUnit(tag)
   279  			if err == nil {
   280  				err = unit.ClearResolved()
   281  			}
   282  		}
   283  		result.Results[i].Error = common.ServerError(err)
   284  	}
   285  	return result, nil
   286  }
   287  
   288  // GetPrincipal returns the result of calling PrincipalName() and
   289  // converting it to a tag, on each given unit.
   290  func (u *uniterBaseAPI) GetPrincipal(args params.Entities) (params.StringBoolResults, error) {
   291  	result := params.StringBoolResults{
   292  		Results: make([]params.StringBoolResult, len(args.Entities)),
   293  	}
   294  	canAccess, err := u.accessUnit()
   295  	if err != nil {
   296  		return params.StringBoolResults{}, err
   297  	}
   298  	for i, entity := range args.Entities {
   299  		tag, err := names.ParseUnitTag(entity.Tag)
   300  		if err != nil {
   301  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   302  			continue
   303  		}
   304  		err = common.ErrPerm
   305  		if canAccess(tag) {
   306  			var unit *state.Unit
   307  			unit, err = u.getUnit(tag)
   308  			if err == nil {
   309  				principal, ok := unit.PrincipalName()
   310  				if principal != "" {
   311  					result.Results[i].Result = names.NewUnitTag(principal).String()
   312  				}
   313  				result.Results[i].Ok = ok
   314  			}
   315  		}
   316  		result.Results[i].Error = common.ServerError(err)
   317  	}
   318  	return result, nil
   319  }
   320  
   321  // Destroy advances all given Alive units' lifecycles as far as
   322  // possible. See state/Unit.Destroy().
   323  func (u *uniterBaseAPI) Destroy(args params.Entities) (params.ErrorResults, error) {
   324  	result := params.ErrorResults{
   325  		Results: make([]params.ErrorResult, len(args.Entities)),
   326  	}
   327  	canAccess, err := u.accessUnit()
   328  	if err != nil {
   329  		return params.ErrorResults{}, err
   330  	}
   331  	for i, entity := range args.Entities {
   332  		tag, err := names.ParseUnitTag(entity.Tag)
   333  		if err != nil {
   334  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   335  			continue
   336  		}
   337  		err = common.ErrPerm
   338  		if canAccess(tag) {
   339  			var unit *state.Unit
   340  			unit, err = u.getUnit(tag)
   341  			if err == nil {
   342  				err = unit.Destroy()
   343  			}
   344  		}
   345  		result.Results[i].Error = common.ServerError(err)
   346  	}
   347  	return result, nil
   348  }
   349  
   350  // DestroyAllSubordinates destroys all subordinates of each given unit.
   351  func (u *uniterBaseAPI) DestroyAllSubordinates(args params.Entities) (params.ErrorResults, error) {
   352  	result := params.ErrorResults{
   353  		Results: make([]params.ErrorResult, len(args.Entities)),
   354  	}
   355  	canAccess, err := u.accessUnit()
   356  	if err != nil {
   357  		return params.ErrorResults{}, err
   358  	}
   359  	for i, entity := range args.Entities {
   360  		tag, err := names.ParseUnitTag(entity.Tag)
   361  		if err != nil {
   362  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   363  			continue
   364  		}
   365  		err = common.ErrPerm
   366  		if canAccess(tag) {
   367  			var unit *state.Unit
   368  			unit, err = u.getUnit(tag)
   369  			if err == nil {
   370  				err = u.destroySubordinates(unit)
   371  			}
   372  		}
   373  		result.Results[i].Error = common.ServerError(err)
   374  	}
   375  	return result, nil
   376  }
   377  
   378  // HasSubordinates returns the whether each given unit has any subordinates.
   379  func (u *uniterBaseAPI) HasSubordinates(args params.Entities) (params.BoolResults, error) {
   380  	result := params.BoolResults{
   381  		Results: make([]params.BoolResult, len(args.Entities)),
   382  	}
   383  	canAccess, err := u.accessUnit()
   384  	if err != nil {
   385  		return params.BoolResults{}, err
   386  	}
   387  	for i, entity := range args.Entities {
   388  		tag, err := names.ParseUnitTag(entity.Tag)
   389  		if err != nil {
   390  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   391  			continue
   392  		}
   393  		err = common.ErrPerm
   394  		if canAccess(tag) {
   395  			var unit *state.Unit
   396  			unit, err = u.getUnit(tag)
   397  			if err == nil {
   398  				subordinates := unit.SubordinateNames()
   399  				result.Results[i].Result = len(subordinates) > 0
   400  			}
   401  		}
   402  		result.Results[i].Error = common.ServerError(err)
   403  	}
   404  	return result, nil
   405  }
   406  
   407  // CharmURL returns the charm URL for all given units or services.
   408  func (u *uniterBaseAPI) CharmURL(args params.Entities) (params.StringBoolResults, error) {
   409  	result := params.StringBoolResults{
   410  		Results: make([]params.StringBoolResult, len(args.Entities)),
   411  	}
   412  	accessUnitOrService := common.AuthEither(u.accessUnit, u.accessService)
   413  	canAccess, err := accessUnitOrService()
   414  	if err != nil {
   415  		return params.StringBoolResults{}, err
   416  	}
   417  	for i, entity := range args.Entities {
   418  		tag, err := names.ParseTag(entity.Tag)
   419  		if err != nil {
   420  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   421  			continue
   422  		}
   423  		err = common.ErrPerm
   424  		if canAccess(tag) {
   425  			var unitOrService state.Entity
   426  			unitOrService, err = u.st.FindEntity(tag)
   427  			if err == nil {
   428  				charmURLer := unitOrService.(interface {
   429  					CharmURL() (*charm.URL, bool)
   430  				})
   431  				curl, ok := charmURLer.CharmURL()
   432  				if curl != nil {
   433  					result.Results[i].Result = curl.String()
   434  					result.Results[i].Ok = ok
   435  				}
   436  			}
   437  		}
   438  		result.Results[i].Error = common.ServerError(err)
   439  	}
   440  	return result, nil
   441  }
   442  
   443  // SetCharmURL sets the charm URL for each given unit. An error will
   444  // be returned if a unit is dead, or the charm URL is not know.
   445  func (u *uniterBaseAPI) SetCharmURL(args params.EntitiesCharmURL) (params.ErrorResults, error) {
   446  	result := params.ErrorResults{
   447  		Results: make([]params.ErrorResult, len(args.Entities)),
   448  	}
   449  	canAccess, err := u.accessUnit()
   450  	if err != nil {
   451  		return params.ErrorResults{}, err
   452  	}
   453  	for i, entity := range args.Entities {
   454  		tag, err := names.ParseUnitTag(entity.Tag)
   455  		if err != nil {
   456  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   457  			continue
   458  		}
   459  		err = common.ErrPerm
   460  		if canAccess(tag) {
   461  			var unit *state.Unit
   462  			unit, err = u.getUnit(tag)
   463  			if err == nil {
   464  				var curl *charm.URL
   465  				curl, err = charm.ParseURL(entity.CharmURL)
   466  				if err == nil {
   467  					err = unit.SetCharmURL(curl)
   468  				}
   469  			}
   470  		}
   471  		result.Results[i].Error = common.ServerError(err)
   472  	}
   473  	return result, nil
   474  }
   475  
   476  // OpenPorts sets the policy of the port range with protocol to be
   477  // opened, for all given units.
   478  func (u *uniterBaseAPI) OpenPorts(args params.EntitiesPortRanges) (params.ErrorResults, error) {
   479  	result := params.ErrorResults{
   480  		Results: make([]params.ErrorResult, len(args.Entities)),
   481  	}
   482  	canAccess, err := u.accessUnit()
   483  	if err != nil {
   484  		return params.ErrorResults{}, err
   485  	}
   486  	for i, entity := range args.Entities {
   487  		tag, err := names.ParseUnitTag(entity.Tag)
   488  		if err != nil {
   489  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   490  			continue
   491  		}
   492  		err = common.ErrPerm
   493  		if canAccess(tag) {
   494  			var unit *state.Unit
   495  			unit, err = u.getUnit(tag)
   496  			if err == nil {
   497  				err = unit.OpenPorts(entity.Protocol, entity.FromPort, entity.ToPort)
   498  			}
   499  		}
   500  		result.Results[i].Error = common.ServerError(err)
   501  	}
   502  	return result, nil
   503  }
   504  
   505  // ClosePorts sets the policy of the port range with protocol to be
   506  // closed, for all given units.
   507  func (u *uniterBaseAPI) ClosePorts(args params.EntitiesPortRanges) (params.ErrorResults, error) {
   508  	result := params.ErrorResults{
   509  		Results: make([]params.ErrorResult, len(args.Entities)),
   510  	}
   511  	canAccess, err := u.accessUnit()
   512  	if err != nil {
   513  		return params.ErrorResults{}, err
   514  	}
   515  	for i, entity := range args.Entities {
   516  		tag, err := names.ParseUnitTag(entity.Tag)
   517  		if err != nil {
   518  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   519  			continue
   520  		}
   521  		err = common.ErrPerm
   522  		if canAccess(tag) {
   523  			var unit *state.Unit
   524  			unit, err = u.getUnit(tag)
   525  			if err == nil {
   526  				err = unit.ClosePorts(entity.Protocol, entity.FromPort, entity.ToPort)
   527  			}
   528  		}
   529  		result.Results[i].Error = common.ServerError(err)
   530  	}
   531  	return result, nil
   532  }
   533  
   534  // OpenPort sets the policy of the port with protocol an number to be
   535  // opened, for all given units.
   536  //
   537  // TODO(dimitern): This is deprecated and is kept for
   538  // backwards-compatibility. Use OpenPorts instead.
   539  func (u *uniterBaseAPI) OpenPort(args params.EntitiesPorts) (params.ErrorResults, error) {
   540  	rangesArgs := params.EntitiesPortRanges{
   541  		Entities: make([]params.EntityPortRange, len(args.Entities)),
   542  	}
   543  	for i, entity := range args.Entities {
   544  		rangesArgs.Entities[i] = params.EntityPortRange{
   545  			Tag:      entity.Tag,
   546  			Protocol: entity.Protocol,
   547  			FromPort: entity.Port,
   548  			ToPort:   entity.Port,
   549  		}
   550  	}
   551  	return u.OpenPorts(rangesArgs)
   552  }
   553  
   554  // ClosePort sets the policy of the port with protocol and number to
   555  // be closed, for all given units.
   556  //
   557  // TODO(dimitern): This is deprecated and is kept for
   558  // backwards-compatibility. Use ClosePorts instead.
   559  func (u *uniterBaseAPI) ClosePort(args params.EntitiesPorts) (params.ErrorResults, error) {
   560  	rangesArgs := params.EntitiesPortRanges{
   561  		Entities: make([]params.EntityPortRange, len(args.Entities)),
   562  	}
   563  	for i, entity := range args.Entities {
   564  		rangesArgs.Entities[i] = params.EntityPortRange{
   565  			Tag:      entity.Tag,
   566  			Protocol: entity.Protocol,
   567  			FromPort: entity.Port,
   568  			ToPort:   entity.Port,
   569  		}
   570  	}
   571  	return u.ClosePorts(rangesArgs)
   572  }
   573  
   574  // WatchConfigSettings returns a NotifyWatcher for observing changes
   575  // to each unit's service configuration settings. See also
   576  // state/watcher.go:Unit.WatchConfigSettings().
   577  func (u *uniterBaseAPI) WatchConfigSettings(args params.Entities) (params.NotifyWatchResults, error) {
   578  	result := params.NotifyWatchResults{
   579  		Results: make([]params.NotifyWatchResult, len(args.Entities)),
   580  	}
   581  	canAccess, err := u.accessUnit()
   582  	if err != nil {
   583  		return params.NotifyWatchResults{}, err
   584  	}
   585  	for i, entity := range args.Entities {
   586  		tag, err := names.ParseUnitTag(entity.Tag)
   587  		if err != nil {
   588  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   589  			continue
   590  		}
   591  		err = common.ErrPerm
   592  		watcherId := ""
   593  		if canAccess(tag) {
   594  			watcherId, err = u.watchOneUnitConfigSettings(tag)
   595  		}
   596  		result.Results[i].NotifyWatcherId = watcherId
   597  		result.Results[i].Error = common.ServerError(err)
   598  	}
   599  	return result, nil
   600  }
   601  
   602  // WatchMeterStatus returns a NotifyWatcher for observing changes
   603  // to each unit's meter status.
   604  func (u *uniterBaseAPI) WatchMeterStatus(args params.Entities) (params.NotifyWatchResults, error) {
   605  	result := params.NotifyWatchResults{
   606  		Results: make([]params.NotifyWatchResult, len(args.Entities)),
   607  	}
   608  	canAccess, err := u.accessUnit()
   609  	if err != nil {
   610  		return params.NotifyWatchResults{}, err
   611  	}
   612  	for i, entity := range args.Entities {
   613  		tag, err := names.ParseUnitTag(entity.Tag)
   614  		if err != nil {
   615  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   616  			continue
   617  		}
   618  		err = common.ErrPerm
   619  		watcherId := ""
   620  		if canAccess(tag) {
   621  			watcherId, err = u.watchOneUnitMeterStatus(tag)
   622  		}
   623  		result.Results[i].NotifyWatcherId = watcherId
   624  		result.Results[i].Error = common.ServerError(err)
   625  	}
   626  	return result, nil
   627  }
   628  
   629  // WatchActionNotifications returns a StringsWatcher for observing
   630  // incoming action calls to a unit. See also state/watcher.go
   631  // Unit.WatchActionNotifications(). This method is called from
   632  // api/uniter/uniter.go WatchActionNotifications().
   633  func (u *uniterBaseAPI) WatchActionNotifications(args params.Entities) (params.StringsWatchResults, error) {
   634  	nothing := params.StringsWatchResults{}
   635  
   636  	result := params.StringsWatchResults{
   637  		Results: make([]params.StringsWatchResult, len(args.Entities)),
   638  	}
   639  	canAccess, err := u.accessUnit()
   640  	if err != nil {
   641  		return nothing, err
   642  	}
   643  	for i, entity := range args.Entities {
   644  		tag, err := names.ParseUnitTag(entity.Tag)
   645  		if err != nil {
   646  			return nothing, err
   647  		}
   648  		err = common.ErrPerm
   649  		if canAccess(tag) {
   650  			result.Results[i], err = u.watchOneUnitActionNotifications(tag)
   651  		}
   652  		result.Results[i].Error = common.ServerError(err)
   653  	}
   654  	return result, nil
   655  }
   656  
   657  // ConfigSettings returns the complete set of service charm config
   658  // settings available to each given unit.
   659  func (u *uniterBaseAPI) ConfigSettings(args params.Entities) (params.ConfigSettingsResults, error) {
   660  	result := params.ConfigSettingsResults{
   661  		Results: make([]params.ConfigSettingsResult, len(args.Entities)),
   662  	}
   663  	canAccess, err := u.accessUnit()
   664  	if err != nil {
   665  		return params.ConfigSettingsResults{}, err
   666  	}
   667  	for i, entity := range args.Entities {
   668  		tag, err := names.ParseUnitTag(entity.Tag)
   669  		if err != nil {
   670  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   671  			continue
   672  		}
   673  		err = common.ErrPerm
   674  		if canAccess(tag) {
   675  			var unit *state.Unit
   676  			unit, err = u.getUnit(tag)
   677  			if err == nil {
   678  				var settings charm.Settings
   679  				settings, err = unit.ConfigSettings()
   680  				if err == nil {
   681  					result.Results[i].Settings = params.ConfigSettings(settings)
   682  				}
   683  			}
   684  		}
   685  		result.Results[i].Error = common.ServerError(err)
   686  	}
   687  	return result, nil
   688  }
   689  
   690  // WatchServiceRelations returns a StringsWatcher, for each given
   691  // service, that notifies of changes to the lifecycles of relations
   692  // involving that service.
   693  func (u *uniterBaseAPI) WatchServiceRelations(args params.Entities) (params.StringsWatchResults, error) {
   694  	result := params.StringsWatchResults{
   695  		Results: make([]params.StringsWatchResult, len(args.Entities)),
   696  	}
   697  	canAccess, err := u.accessService()
   698  	if err != nil {
   699  		return params.StringsWatchResults{}, err
   700  	}
   701  	for i, entity := range args.Entities {
   702  		tag, err := names.ParseServiceTag(entity.Tag)
   703  		if err != nil {
   704  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   705  			continue
   706  		}
   707  		err = common.ErrPerm
   708  		if canAccess(tag) {
   709  			result.Results[i], err = u.watchOneServiceRelations(tag)
   710  		}
   711  		result.Results[i].Error = common.ServerError(err)
   712  	}
   713  	return result, nil
   714  }
   715  
   716  // CharmArchiveSha256 returns the SHA256 digest of the charm archive
   717  // (bundle) data for each charm url in the given parameters.
   718  func (u *uniterBaseAPI) CharmArchiveSha256(args params.CharmURLs) (params.StringResults, error) {
   719  	result := params.StringResults{
   720  		Results: make([]params.StringResult, len(args.URLs)),
   721  	}
   722  	for i, arg := range args.URLs {
   723  		curl, err := charm.ParseURL(arg.URL)
   724  		if err != nil {
   725  			err = common.ErrPerm
   726  		} else {
   727  			var sch *state.Charm
   728  			sch, err = u.st.Charm(curl)
   729  			if errors.IsNotFound(err) {
   730  				err = common.ErrPerm
   731  			}
   732  			if err == nil {
   733  				result.Results[i].Result = sch.BundleSha256()
   734  			}
   735  		}
   736  		result.Results[i].Error = common.ServerError(err)
   737  	}
   738  	return result, nil
   739  }
   740  
   741  // CharmArchiveURLs returns the URLS for the charm archive
   742  // (bundle) data for each charm url in the given parameters.
   743  func (u *uniterBaseAPI) CharmArchiveURLs(args params.CharmURLs) (params.StringsResults, error) {
   744  	apiHostPorts, err := u.st.APIHostPorts()
   745  	if err != nil {
   746  		return params.StringsResults{}, err
   747  	}
   748  	envUUID := u.st.EnvironUUID()
   749  	result := params.StringsResults{
   750  		Results: make([]params.StringsResult, len(args.URLs)),
   751  	}
   752  	for i, curl := range args.URLs {
   753  		if _, err := charm.ParseURL(curl.URL); err != nil {
   754  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   755  			continue
   756  		}
   757  		urlPath := "/"
   758  		if envUUID != "" {
   759  			urlPath = path.Join(urlPath, "environment", envUUID)
   760  		}
   761  		urlPath = path.Join(urlPath, "charms")
   762  		archiveURLs := make([]string, len(apiHostPorts))
   763  		for j, server := range apiHostPorts {
   764  			archiveURL := &url.URL{
   765  				Scheme: "https",
   766  				Host:   network.SelectInternalHostPort(server, false),
   767  				Path:   urlPath,
   768  			}
   769  			q := archiveURL.Query()
   770  			q.Set("url", curl.URL)
   771  			q.Set("file", "*")
   772  			archiveURL.RawQuery = q.Encode()
   773  			archiveURLs[j] = archiveURL.String()
   774  		}
   775  		result.Results[i].Result = archiveURLs
   776  	}
   777  	return result, nil
   778  }
   779  
   780  // Relation returns information about all given relation/unit pairs,
   781  // including their id, key and the local endpoint.
   782  func (u *uniterBaseAPI) Relation(args params.RelationUnits) (params.RelationResults, error) {
   783  	result := params.RelationResults{
   784  		Results: make([]params.RelationResult, len(args.RelationUnits)),
   785  	}
   786  	canAccess, err := u.accessUnit()
   787  	if err != nil {
   788  		return params.RelationResults{}, err
   789  	}
   790  	for i, rel := range args.RelationUnits {
   791  		relParams, err := u.getOneRelation(canAccess, rel.Relation, rel.Unit)
   792  		if err == nil {
   793  			result.Results[i] = relParams
   794  		}
   795  		result.Results[i].Error = common.ServerError(err)
   796  	}
   797  	return result, nil
   798  }
   799  
   800  // Actions returns the Actions by Tags passed and ensures that the Unit asking
   801  // for them is the same Unit that has the Actions.
   802  func (u *uniterBaseAPI) Actions(args params.Entities) (params.ActionsQueryResults, error) {
   803  	nothing := params.ActionsQueryResults{}
   804  
   805  	actionFn, err := u.authAndActionFromTagFn()
   806  	if err != nil {
   807  		return nothing, err
   808  	}
   809  
   810  	results := params.ActionsQueryResults{
   811  		Results: make([]params.ActionsQueryResult, len(args.Entities)),
   812  	}
   813  
   814  	for i, arg := range args.Entities {
   815  		action, err := actionFn(arg.Tag)
   816  		if err != nil {
   817  			results.Results[i].Error = common.ServerError(err)
   818  			continue
   819  		}
   820  		if action.Status() != state.ActionPending {
   821  			results.Results[i].Error = common.ServerError(common.ErrActionNotAvailable)
   822  			continue
   823  		}
   824  		results.Results[i].Action.Action = &params.Action{
   825  			Name:       action.Name(),
   826  			Parameters: action.Parameters(),
   827  		}
   828  	}
   829  
   830  	return results, nil
   831  }
   832  
   833  // BeginActions marks the actions represented by the passed in Tags as running.
   834  func (u *uniterBaseAPI) BeginActions(args params.Entities) (params.ErrorResults, error) {
   835  	nothing := params.ErrorResults{}
   836  
   837  	actionFn, err := u.authAndActionFromTagFn()
   838  	if err != nil {
   839  		return nothing, err
   840  	}
   841  
   842  	results := params.ErrorResults{Results: make([]params.ErrorResult, len(args.Entities))}
   843  
   844  	for i, arg := range args.Entities {
   845  		action, err := actionFn(arg.Tag)
   846  		if err != nil {
   847  			results.Results[i].Error = common.ServerError(err)
   848  			continue
   849  		}
   850  
   851  		_, err = action.Begin()
   852  		if err != nil {
   853  			results.Results[i].Error = common.ServerError(err)
   854  			continue
   855  		}
   856  	}
   857  
   858  	return results, nil
   859  }
   860  
   861  // FinishActions saves the result of a completed Action
   862  func (u *uniterBaseAPI) FinishActions(args params.ActionExecutionResults) (params.ErrorResults, error) {
   863  	nothing := params.ErrorResults{}
   864  
   865  	actionFn, err := u.authAndActionFromTagFn()
   866  	if err != nil {
   867  		return nothing, err
   868  	}
   869  
   870  	results := params.ErrorResults{Results: make([]params.ErrorResult, len(args.Results))}
   871  
   872  	for i, arg := range args.Results {
   873  		action, err := actionFn(arg.ActionTag)
   874  		if err != nil {
   875  			results.Results[i].Error = common.ServerError(err)
   876  			continue
   877  		}
   878  		actionResults, err := paramsActionExecutionResultsToStateActionResults(arg)
   879  		if err != nil {
   880  			results.Results[i].Error = common.ServerError(err)
   881  			continue
   882  		}
   883  
   884  		_, err = action.Finish(actionResults)
   885  		if err != nil {
   886  			results.Results[i].Error = common.ServerError(err)
   887  			continue
   888  		}
   889  	}
   890  
   891  	return results, nil
   892  }
   893  
   894  // paramsActionExecutionResultsToStateActionResults does exactly what
   895  // the name implies.
   896  func paramsActionExecutionResultsToStateActionResults(arg params.ActionExecutionResult) (state.ActionResults, error) {
   897  	var status state.ActionStatus
   898  	switch arg.Status {
   899  	case params.ActionCancelled:
   900  		status = state.ActionCancelled
   901  	case params.ActionCompleted:
   902  		status = state.ActionCompleted
   903  	case params.ActionFailed:
   904  		status = state.ActionFailed
   905  	case params.ActionPending:
   906  		status = state.ActionPending
   907  	default:
   908  		return state.ActionResults{}, errors.Errorf("unrecognized action status '%s'", arg.Status)
   909  	}
   910  	return state.ActionResults{
   911  		Status:  status,
   912  		Results: arg.Results,
   913  		Message: arg.Message,
   914  	}, nil
   915  }
   916  
   917  // RelationById returns information about all given relations,
   918  // specified by their ids, including their key and the local
   919  // endpoint.
   920  func (u *uniterBaseAPI) RelationById(args params.RelationIds) (params.RelationResults, error) {
   921  	result := params.RelationResults{
   922  		Results: make([]params.RelationResult, len(args.RelationIds)),
   923  	}
   924  	for i, relId := range args.RelationIds {
   925  		relParams, err := u.getOneRelationById(relId)
   926  		if err == nil {
   927  			result.Results[i] = relParams
   928  		}
   929  		result.Results[i].Error = common.ServerError(err)
   930  	}
   931  	return result, nil
   932  }
   933  
   934  // JoinedRelations returns the tags of all relations for which each supplied unit
   935  // has entered scope. It should be called RelationsInScope, but it's not convenient
   936  // to make that change until we have versioned APIs.
   937  func (u *uniterBaseAPI) JoinedRelations(args params.Entities) (params.StringsResults, error) {
   938  	result := params.StringsResults{
   939  		Results: make([]params.StringsResult, len(args.Entities)),
   940  	}
   941  	if len(args.Entities) == 0 {
   942  		return result, nil
   943  	}
   944  	canRead, err := u.accessUnit()
   945  	if err != nil {
   946  		return params.StringsResults{}, err
   947  	}
   948  	for i, entity := range args.Entities {
   949  		tag, err := names.ParseUnitTag(entity.Tag)
   950  		if err != nil {
   951  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   952  			continue
   953  		}
   954  		err = common.ErrPerm
   955  		if canRead(tag) {
   956  			var unit *state.Unit
   957  			unit, err = u.getUnit(tag)
   958  			if err == nil {
   959  				result.Results[i].Result, err = relationsInScopeTags(unit)
   960  			}
   961  		}
   962  		result.Results[i].Error = common.ServerError(err)
   963  	}
   964  	return result, nil
   965  }
   966  
   967  // CurrentEnvironUUID returns the UUID for the current juju environment.
   968  func (u *uniterBaseAPI) CurrentEnvironUUID() (params.StringResult, error) {
   969  	result := params.StringResult{}
   970  	env, err := u.st.Environment()
   971  	if err == nil {
   972  		result.Result = env.UUID()
   973  	}
   974  	return result, err
   975  }
   976  
   977  // CurrentEnvironment returns the name and UUID for the current juju environment.
   978  func (u *uniterBaseAPI) CurrentEnvironment() (params.EnvironmentResult, error) {
   979  	result := params.EnvironmentResult{}
   980  	env, err := u.st.Environment()
   981  	if err == nil {
   982  		result.Name = env.Name()
   983  		result.UUID = env.UUID()
   984  	}
   985  	return result, err
   986  }
   987  
   988  // ProviderType returns the provider type used by the current juju
   989  // environment.
   990  //
   991  // TODO(dimitern): Refactor the uniter to call this instead of calling
   992  // EnvironConfig() just to get the provider type. Once we have machine
   993  // addresses, this might be completely unnecessary though.
   994  func (u *uniterBaseAPI) ProviderType() (params.StringResult, error) {
   995  	result := params.StringResult{}
   996  	cfg, err := u.st.EnvironConfig()
   997  	if err == nil {
   998  		result.Result = cfg.Type()
   999  	}
  1000  	return result, err
  1001  }
  1002  
  1003  // EnterScope ensures each unit has entered its scope in the relation,
  1004  // for all of the given relation/unit pairs. See also
  1005  // state.RelationUnit.EnterScope().
  1006  func (u *uniterBaseAPI) EnterScope(args params.RelationUnits) (params.ErrorResults, error) {
  1007  	result := params.ErrorResults{
  1008  		Results: make([]params.ErrorResult, len(args.RelationUnits)),
  1009  	}
  1010  	canAccess, err := u.accessUnit()
  1011  	if err != nil {
  1012  		return params.ErrorResults{}, err
  1013  	}
  1014  	for i, arg := range args.RelationUnits {
  1015  		tag, err := names.ParseUnitTag(arg.Unit)
  1016  		if err != nil {
  1017  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1018  			continue
  1019  		}
  1020  		relUnit, err := u.getRelationUnit(canAccess, arg.Relation, tag)
  1021  		if err == nil {
  1022  			// Construct the settings, passing the unit's
  1023  			// private address (we already know it).
  1024  			privateAddress, _ := relUnit.PrivateAddress()
  1025  			settings := map[string]interface{}{
  1026  				"private-address": privateAddress,
  1027  			}
  1028  			err = relUnit.EnterScope(settings)
  1029  		}
  1030  		result.Results[i].Error = common.ServerError(err)
  1031  	}
  1032  	return result, nil
  1033  }
  1034  
  1035  // LeaveScope signals each unit has left its scope in the relation,
  1036  // for all of the given relation/unit pairs. See also
  1037  // state.RelationUnit.LeaveScope().
  1038  func (u *uniterBaseAPI) LeaveScope(args params.RelationUnits) (params.ErrorResults, error) {
  1039  	result := params.ErrorResults{
  1040  		Results: make([]params.ErrorResult, len(args.RelationUnits)),
  1041  	}
  1042  	canAccess, err := u.accessUnit()
  1043  	if err != nil {
  1044  		return params.ErrorResults{}, err
  1045  	}
  1046  	for i, arg := range args.RelationUnits {
  1047  		unit, err := names.ParseUnitTag(arg.Unit)
  1048  		if err != nil {
  1049  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1050  			continue
  1051  		}
  1052  		relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit)
  1053  		if err == nil {
  1054  			err = relUnit.LeaveScope()
  1055  		}
  1056  		result.Results[i].Error = common.ServerError(err)
  1057  	}
  1058  	return result, nil
  1059  }
  1060  
  1061  // ReadSettings returns the local settings of each given set of
  1062  // relation/unit.
  1063  func (u *uniterBaseAPI) ReadSettings(args params.RelationUnits) (params.SettingsResults, error) {
  1064  	result := params.SettingsResults{
  1065  		Results: make([]params.SettingsResult, len(args.RelationUnits)),
  1066  	}
  1067  	canAccess, err := u.accessUnit()
  1068  	if err != nil {
  1069  		return params.SettingsResults{}, err
  1070  	}
  1071  	for i, arg := range args.RelationUnits {
  1072  		unit, err := names.ParseUnitTag(arg.Unit)
  1073  		if err != nil {
  1074  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1075  			continue
  1076  		}
  1077  		relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit)
  1078  		if err == nil {
  1079  			var settings *state.Settings
  1080  			settings, err = relUnit.Settings()
  1081  			if err == nil {
  1082  				result.Results[i].Settings, err = convertRelationSettings(settings.Map())
  1083  			}
  1084  		}
  1085  		result.Results[i].Error = common.ServerError(err)
  1086  	}
  1087  	return result, nil
  1088  }
  1089  
  1090  // ReadRemoteSettings returns the remote settings of each given set of
  1091  // relation/local unit/remote unit.
  1092  func (u *uniterBaseAPI) ReadRemoteSettings(args params.RelationUnitPairs) (params.SettingsResults, error) {
  1093  	result := params.SettingsResults{
  1094  		Results: make([]params.SettingsResult, len(args.RelationUnitPairs)),
  1095  	}
  1096  	canAccess, err := u.accessUnit()
  1097  	if err != nil {
  1098  		return params.SettingsResults{}, err
  1099  	}
  1100  	for i, arg := range args.RelationUnitPairs {
  1101  		unit, err := names.ParseUnitTag(arg.LocalUnit)
  1102  		if err != nil {
  1103  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1104  			continue
  1105  		}
  1106  		relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit)
  1107  		if err == nil {
  1108  			// TODO(dfc) rework this logic
  1109  			remoteUnit := ""
  1110  			remoteUnit, err = u.checkRemoteUnit(relUnit, arg.RemoteUnit)
  1111  			if err == nil {
  1112  				var settings map[string]interface{}
  1113  				settings, err = relUnit.ReadSettings(remoteUnit)
  1114  				if err == nil {
  1115  					result.Results[i].Settings, err = convertRelationSettings(settings)
  1116  				}
  1117  			}
  1118  		}
  1119  		result.Results[i].Error = common.ServerError(err)
  1120  	}
  1121  	return result, nil
  1122  }
  1123  
  1124  // UpdateSettings persists all changes made to the local settings of
  1125  // all given pairs of relation and unit. Keys with empty values are
  1126  // considered a signal to delete these values.
  1127  func (u *uniterBaseAPI) UpdateSettings(args params.RelationUnitsSettings) (params.ErrorResults, error) {
  1128  	result := params.ErrorResults{
  1129  		Results: make([]params.ErrorResult, len(args.RelationUnits)),
  1130  	}
  1131  	canAccess, err := u.accessUnit()
  1132  	if err != nil {
  1133  		return params.ErrorResults{}, err
  1134  	}
  1135  	for i, arg := range args.RelationUnits {
  1136  		unit, err := names.ParseUnitTag(arg.Unit)
  1137  		if err != nil {
  1138  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1139  			continue
  1140  		}
  1141  		relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit)
  1142  		if err == nil {
  1143  			var settings *state.Settings
  1144  			settings, err = relUnit.Settings()
  1145  			if err == nil {
  1146  				for k, v := range arg.Settings {
  1147  					if v == "" {
  1148  						settings.Delete(k)
  1149  					} else {
  1150  						settings.Set(k, v)
  1151  					}
  1152  				}
  1153  				_, err = settings.Write()
  1154  			}
  1155  		}
  1156  		result.Results[i].Error = common.ServerError(err)
  1157  	}
  1158  	return result, nil
  1159  }
  1160  
  1161  // WatchRelationUnits returns a RelationUnitsWatcher for observing
  1162  // changes to every unit in the supplied relation that is visible to
  1163  // the supplied unit. See also state/watcher.go:RelationUnit.Watch().
  1164  func (u *uniterBaseAPI) WatchRelationUnits(args params.RelationUnits) (params.RelationUnitsWatchResults, error) {
  1165  	result := params.RelationUnitsWatchResults{
  1166  		Results: make([]params.RelationUnitsWatchResult, len(args.RelationUnits)),
  1167  	}
  1168  	canAccess, err := u.accessUnit()
  1169  	if err != nil {
  1170  		return params.RelationUnitsWatchResults{}, err
  1171  	}
  1172  	for i, arg := range args.RelationUnits {
  1173  		unit, err := names.ParseUnitTag(arg.Unit)
  1174  		if err != nil {
  1175  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1176  			continue
  1177  		}
  1178  		relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit)
  1179  		if err == nil {
  1180  			result.Results[i], err = u.watchOneRelationUnit(relUnit)
  1181  		}
  1182  		result.Results[i].Error = common.ServerError(err)
  1183  	}
  1184  	return result, nil
  1185  }
  1186  
  1187  // WatchAddresses returns a NotifyWatcher for observing changes
  1188  // to each unit's addresses.
  1189  func (u *uniterBaseAPI) WatchUnitAddresses(args params.Entities) (params.NotifyWatchResults, error) {
  1190  	result := params.NotifyWatchResults{
  1191  		Results: make([]params.NotifyWatchResult, len(args.Entities)),
  1192  	}
  1193  	canAccess, err := u.accessUnit()
  1194  	if err != nil {
  1195  		return params.NotifyWatchResults{}, err
  1196  	}
  1197  	for i, entity := range args.Entities {
  1198  		unit, err := names.ParseUnitTag(entity.Tag)
  1199  		if err != nil {
  1200  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1201  			continue
  1202  		}
  1203  		err = common.ErrPerm
  1204  		watcherId := ""
  1205  		if canAccess(unit) {
  1206  			watcherId, err = u.watchOneUnitAddresses(unit)
  1207  		}
  1208  		result.Results[i].NotifyWatcherId = watcherId
  1209  		result.Results[i].Error = common.ServerError(err)
  1210  	}
  1211  	return result, nil
  1212  }
  1213  
  1214  // AddMetrics adds the metrics for the specified unit.
  1215  func (u *uniterBaseAPI) AddMetrics(args params.MetricsParams) (params.ErrorResults, error) {
  1216  	result := params.ErrorResults{
  1217  		Results: make([]params.ErrorResult, len(args.Metrics)),
  1218  	}
  1219  	canAccess, err := u.accessUnit()
  1220  	if err != nil {
  1221  		return params.ErrorResults{}, common.ErrPerm
  1222  	}
  1223  	for i, unitMetrics := range args.Metrics {
  1224  		tag, err := names.ParseUnitTag(unitMetrics.Tag)
  1225  		if err != nil {
  1226  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1227  			continue
  1228  		}
  1229  		err = common.ErrPerm
  1230  		if canAccess(tag) {
  1231  			var unit *state.Unit
  1232  			unit, err = u.getUnit(tag)
  1233  			if err == nil {
  1234  				metricBatch := make([]state.Metric, len(unitMetrics.Metrics))
  1235  				for j, metric := range unitMetrics.Metrics {
  1236  					// TODO (tasdomas) 2014-08-26: set credentials for metrics when available
  1237  					metricBatch[j] = state.Metric{
  1238  						Key:   metric.Key,
  1239  						Value: metric.Value,
  1240  						Time:  metric.Time,
  1241  					}
  1242  				}
  1243  				_, err = unit.AddMetrics(time.Now(), metricBatch)
  1244  			}
  1245  		}
  1246  		result.Results[i].Error = common.ServerError(err)
  1247  	}
  1248  	return result, nil
  1249  }
  1250  
  1251  // GetMeterStatus returns meter status information for each unit.
  1252  func (u *uniterBaseAPI) GetMeterStatus(args params.Entities) (params.MeterStatusResults, error) {
  1253  	result := params.MeterStatusResults{
  1254  		Results: make([]params.MeterStatusResult, len(args.Entities)),
  1255  	}
  1256  	canAccess, err := u.accessUnit()
  1257  	if err != nil {
  1258  		return params.MeterStatusResults{}, common.ErrPerm
  1259  	}
  1260  	for i, entity := range args.Entities {
  1261  		unitTag, err := names.ParseUnitTag(entity.Tag)
  1262  		if err != nil {
  1263  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1264  			continue
  1265  		}
  1266  		err = common.ErrPerm
  1267  		var code string
  1268  		var info string
  1269  		if canAccess(unitTag) {
  1270  			var unit *state.Unit
  1271  			unit, err = u.getUnit(unitTag)
  1272  			if err == nil {
  1273  				code, info, err = unit.GetMeterStatus()
  1274  			}
  1275  		}
  1276  		result.Results[i].Code = code
  1277  		result.Results[i].Info = info
  1278  		result.Results[i].Error = common.ServerError(err)
  1279  	}
  1280  	return result, nil
  1281  }
  1282  
  1283  func (u *uniterBaseAPI) getUnit(tag names.UnitTag) (*state.Unit, error) {
  1284  	return u.st.Unit(tag.Id())
  1285  }
  1286  
  1287  func (u *uniterBaseAPI) getService(tag names.ServiceTag) (*state.Service, error) {
  1288  	return u.st.Service(tag.Id())
  1289  }
  1290  
  1291  func (u *uniterBaseAPI) getRelationUnit(canAccess common.AuthFunc, relTag string, unitTag names.UnitTag) (*state.RelationUnit, error) {
  1292  	rel, unit, err := u.getRelationAndUnit(canAccess, relTag, unitTag)
  1293  	if err != nil {
  1294  		return nil, err
  1295  	}
  1296  	return rel.Unit(unit)
  1297  }
  1298  
  1299  func (u *uniterBaseAPI) getOneRelationById(relId int) (params.RelationResult, error) {
  1300  	nothing := params.RelationResult{}
  1301  	rel, err := u.st.Relation(relId)
  1302  	if errors.IsNotFound(err) {
  1303  		return nothing, common.ErrPerm
  1304  	} else if err != nil {
  1305  		return nothing, err
  1306  	}
  1307  	tag := u.auth.GetAuthTag()
  1308  	switch tag.(type) {
  1309  	case names.UnitTag:
  1310  		// do nothing
  1311  	default:
  1312  		panic("authenticated entity is not a unit")
  1313  	}
  1314  	unit, err := u.st.FindEntity(tag)
  1315  	if err != nil {
  1316  		return nothing, err
  1317  	}
  1318  	// Use the currently authenticated unit to get the endpoint.
  1319  	result, err := u.prepareRelationResult(rel, unit.(*state.Unit))
  1320  	if err != nil {
  1321  		// An error from prepareRelationResult means the authenticated
  1322  		// unit's service is not part of the requested
  1323  		// relation. That's why it's appropriate to return ErrPerm
  1324  		// here.
  1325  		return nothing, common.ErrPerm
  1326  	}
  1327  	return result, nil
  1328  }
  1329  
  1330  func (u *uniterBaseAPI) getRelationAndUnit(canAccess common.AuthFunc, relTag string, unitTag names.UnitTag) (*state.Relation, *state.Unit, error) {
  1331  	tag, err := names.ParseRelationTag(relTag)
  1332  	if err != nil {
  1333  		return nil, nil, common.ErrPerm
  1334  	}
  1335  	rel, err := u.st.KeyRelation(tag.Id())
  1336  	if errors.IsNotFound(err) {
  1337  		return nil, nil, common.ErrPerm
  1338  	} else if err != nil {
  1339  		return nil, nil, err
  1340  	}
  1341  	if !canAccess(unitTag) {
  1342  		return nil, nil, common.ErrPerm
  1343  	}
  1344  	unit, err := u.getUnit(unitTag)
  1345  	return rel, unit, err
  1346  }
  1347  
  1348  func (u *uniterBaseAPI) prepareRelationResult(rel *state.Relation, unit *state.Unit) (params.RelationResult, error) {
  1349  	nothing := params.RelationResult{}
  1350  	ep, err := rel.Endpoint(unit.ServiceName())
  1351  	if err != nil {
  1352  		// An error here means the unit's service is not part of the
  1353  		// relation.
  1354  		return nothing, err
  1355  	}
  1356  	return params.RelationResult{
  1357  		Id:   rel.Id(),
  1358  		Key:  rel.String(),
  1359  		Life: params.Life(rel.Life().String()),
  1360  		Endpoint: multiwatcher.Endpoint{
  1361  			ServiceName: ep.ServiceName,
  1362  			Relation:    ep.Relation,
  1363  		},
  1364  	}, nil
  1365  }
  1366  
  1367  func (u *uniterBaseAPI) getOneRelation(canAccess common.AuthFunc, relTag, unitTag string) (params.RelationResult, error) {
  1368  	nothing := params.RelationResult{}
  1369  	tag, err := names.ParseUnitTag(unitTag)
  1370  	if err != nil {
  1371  		return nothing, common.ErrPerm
  1372  	}
  1373  	rel, unit, err := u.getRelationAndUnit(canAccess, relTag, tag)
  1374  	if err != nil {
  1375  		return nothing, err
  1376  	}
  1377  	return u.prepareRelationResult(rel, unit)
  1378  }
  1379  
  1380  func (u *uniterBaseAPI) destroySubordinates(principal *state.Unit) error {
  1381  	subordinates := principal.SubordinateNames()
  1382  	for _, subName := range subordinates {
  1383  		unit, err := u.getUnit(names.NewUnitTag(subName))
  1384  		if err != nil {
  1385  			return err
  1386  		}
  1387  		if err = unit.Destroy(); err != nil {
  1388  			return err
  1389  		}
  1390  	}
  1391  	return nil
  1392  }
  1393  
  1394  func (u *uniterBaseAPI) watchOneServiceRelations(tag names.ServiceTag) (params.StringsWatchResult, error) {
  1395  	nothing := params.StringsWatchResult{}
  1396  	service, err := u.getService(tag)
  1397  	if err != nil {
  1398  		return nothing, err
  1399  	}
  1400  	watch := service.WatchRelations()
  1401  	// Consume the initial event and forward it to the result.
  1402  	if changes, ok := <-watch.Changes(); ok {
  1403  		return params.StringsWatchResult{
  1404  			StringsWatcherId: u.resources.Register(watch),
  1405  			Changes:          changes,
  1406  		}, nil
  1407  	}
  1408  	return nothing, watcher.EnsureErr(watch)
  1409  }
  1410  
  1411  func (u *uniterBaseAPI) watchOneUnitConfigSettings(tag names.UnitTag) (string, error) {
  1412  	unit, err := u.getUnit(tag)
  1413  	if err != nil {
  1414  		return "", err
  1415  	}
  1416  	watch, err := unit.WatchConfigSettings()
  1417  	if err != nil {
  1418  		return "", err
  1419  	}
  1420  	// Consume the initial event. Technically, API
  1421  	// calls to Watch 'transmit' the initial event
  1422  	// in the Watch response. But NotifyWatchers
  1423  	// have no state to transmit.
  1424  	if _, ok := <-watch.Changes(); ok {
  1425  		return u.resources.Register(watch), nil
  1426  	}
  1427  	return "", watcher.EnsureErr(watch)
  1428  }
  1429  
  1430  func (u *uniterBaseAPI) watchOneUnitActionNotifications(tag names.UnitTag) (params.StringsWatchResult, error) {
  1431  	nothing := params.StringsWatchResult{}
  1432  	unit, err := u.getUnit(tag)
  1433  	if err != nil {
  1434  		return nothing, err
  1435  	}
  1436  	watch := unit.WatchActionNotifications()
  1437  
  1438  	if changes, ok := <-watch.Changes(); ok {
  1439  		return params.StringsWatchResult{
  1440  			StringsWatcherId: u.resources.Register(watch),
  1441  			Changes:          changes,
  1442  		}, nil
  1443  	}
  1444  	return nothing, watcher.EnsureErr(watch)
  1445  }
  1446  
  1447  func (u *uniterBaseAPI) watchOneUnitAddresses(tag names.UnitTag) (string, error) {
  1448  	unit, err := u.getUnit(tag)
  1449  	if err != nil {
  1450  		return "", err
  1451  	}
  1452  	machineId, err := unit.AssignedMachineId()
  1453  	if err != nil {
  1454  		return "", err
  1455  	}
  1456  	machine, err := u.st.Machine(machineId)
  1457  	if err != nil {
  1458  		return "", err
  1459  	}
  1460  	watch := machine.WatchAddresses()
  1461  	// Consume the initial event. Technically, API
  1462  	// calls to Watch 'transmit' the initial event
  1463  	// in the Watch response. But NotifyWatchers
  1464  	// have no state to transmit.
  1465  	if _, ok := <-watch.Changes(); ok {
  1466  		return u.resources.Register(watch), nil
  1467  	}
  1468  	return "", watcher.EnsureErr(watch)
  1469  }
  1470  
  1471  func (u *uniterBaseAPI) watchOneRelationUnit(relUnit *state.RelationUnit) (params.RelationUnitsWatchResult, error) {
  1472  	watch := relUnit.Watch()
  1473  	// Consume the initial event and forward it to the result.
  1474  	if changes, ok := <-watch.Changes(); ok {
  1475  		return params.RelationUnitsWatchResult{
  1476  			RelationUnitsWatcherId: u.resources.Register(watch),
  1477  			Changes:                changes,
  1478  		}, nil
  1479  	}
  1480  	return params.RelationUnitsWatchResult{}, watcher.EnsureErr(watch)
  1481  }
  1482  
  1483  func (u *uniterBaseAPI) watchOneUnitMeterStatus(tag names.UnitTag) (string, error) {
  1484  	unit, err := u.getUnit(tag)
  1485  	if err != nil {
  1486  		return "", err
  1487  	}
  1488  	watch := unit.WatchMeterStatus()
  1489  	if _, ok := <-watch.Changes(); ok {
  1490  		return u.resources.Register(watch), nil
  1491  	}
  1492  	return "", watcher.EnsureErr(watch)
  1493  }
  1494  
  1495  func (u *uniterBaseAPI) checkRemoteUnit(relUnit *state.RelationUnit, remoteUnitTag string) (string, error) {
  1496  	// Make sure the unit is indeed remote.
  1497  	if remoteUnitTag == u.auth.GetAuthTag().String() {
  1498  		return "", common.ErrPerm
  1499  	}
  1500  	// Check remoteUnit is indeed related. Note that we don't want to actually get
  1501  	// the *Unit, because it might have been removed; but its relation settings will
  1502  	// persist until the relation itself has been removed (and must remain accessible
  1503  	// because the local unit's view of reality may be time-shifted).
  1504  	tag, err := names.ParseUnitTag(remoteUnitTag)
  1505  	if err != nil {
  1506  		return "", common.ErrPerm
  1507  	}
  1508  	remoteUnitName := tag.Id()
  1509  	remoteServiceName, err := names.UnitService(remoteUnitName)
  1510  	if err != nil {
  1511  		return "", common.ErrPerm
  1512  	}
  1513  	rel := relUnit.Relation()
  1514  	_, err = rel.RelatedEndpoints(remoteServiceName)
  1515  	if err != nil {
  1516  		return "", common.ErrPerm
  1517  	}
  1518  	return remoteUnitName, nil
  1519  }
  1520  
  1521  // authAndActionFromTagFn first authenticates the request, and then returns
  1522  // a function with which to authenticate and retrieve each action in the
  1523  // request.
  1524  func (u *uniterBaseAPI) authAndActionFromTagFn() (func(string) (*state.Action, error), error) {
  1525  	canAccess, err := u.accessUnit()
  1526  	if err != nil {
  1527  		return nil, err
  1528  	}
  1529  	unit, ok := u.auth.GetAuthTag().(names.UnitTag)
  1530  	if !ok {
  1531  		return nil, fmt.Errorf("calling entity is not a unit")
  1532  	}
  1533  
  1534  	return func(tag string) (*state.Action, error) {
  1535  		actionTag, err := names.ParseActionTag(tag)
  1536  		if err != nil {
  1537  			return nil, err
  1538  		}
  1539  		action, err := u.st.ActionByTag(actionTag)
  1540  		if err != nil {
  1541  			return nil, err
  1542  		}
  1543  		receiverTag, err := names.ActionReceiverTag(action.Receiver())
  1544  		if err != nil {
  1545  			return nil, err
  1546  		}
  1547  		if unit != receiverTag {
  1548  			return nil, common.ErrPerm
  1549  		}
  1550  
  1551  		if !canAccess(receiverTag) {
  1552  			return nil, common.ErrPerm
  1553  		}
  1554  		return action, nil
  1555  	}, nil
  1556  }
  1557  
  1558  func convertRelationSettings(settings map[string]interface{}) (params.Settings, error) {
  1559  	result := make(params.Settings)
  1560  	for k, v := range settings {
  1561  		// All relation settings should be strings.
  1562  		sval, ok := v.(string)
  1563  		if !ok {
  1564  			return nil, fmt.Errorf("unexpected relation setting %q: expected string, got %T", k, v)
  1565  		}
  1566  		result[k] = sval
  1567  	}
  1568  	return result, nil
  1569  }
  1570  
  1571  func relationsInScopeTags(unit *state.Unit) ([]string, error) {
  1572  	relations, err := unit.RelationsInScope()
  1573  	if err != nil {
  1574  		return nil, err
  1575  	}
  1576  	tags := make([]string, len(relations))
  1577  	for i, relation := range relations {
  1578  		tags[i] = relation.Tag().String()
  1579  	}
  1580  	return tags, nil
  1581  }
  1582  
  1583  func leadershipSettingsAccessorFactory(
  1584  	st *state.State,
  1585  	resources *common.Resources,
  1586  	auth common.Authorizer,
  1587  ) *leadershipapiserver.LeadershipSettingsAccessor {
  1588  	registerWatcher := func(serviceId string) (string, error) {
  1589  		settingsWatcher := st.WatchLeadershipSettings(serviceId)
  1590  		if _, ok := <-settingsWatcher.Changes(); ok {
  1591  			return resources.Register(settingsWatcher), nil
  1592  		}
  1593  
  1594  		return "", watcher.EnsureErr(settingsWatcher)
  1595  	}
  1596  	// TODO(katco-): <2015-01-21 Wed>
  1597  	// Due to time constraints, we're translating between
  1598  	// map[string]interface{} and map[string]string. At some point we
  1599  	// should support a native read of this format straight from
  1600  	// state.
  1601  	getSettings := func(serviceId string) (map[string]string, error) {
  1602  		settings, err := st.ReadSettings(state.LeadershipSettingsDocId(serviceId))
  1603  		if err != nil {
  1604  			return nil, err
  1605  		}
  1606  		// Perform the conversion
  1607  		rawMap := settings.Map()
  1608  		leadershipSettings := make(map[string]string)
  1609  		for k, v := range rawMap {
  1610  			leadershipSettings[k] = v.(string)
  1611  		}
  1612  		return leadershipSettings, nil
  1613  	}
  1614  	writeSettings := func(serviceId string, settings map[string]string) error {
  1615  		currentSettings, err := st.ReadLeadershipSettings(serviceId)
  1616  		if err != nil {
  1617  			return err
  1618  		}
  1619  		rawSettings := make(map[string]interface{})
  1620  		for k, v := range settings {
  1621  			rawSettings[k] = v
  1622  		}
  1623  		currentSettings.Update(rawSettings)
  1624  		_, err = currentSettings.Write()
  1625  		return errors.Annotate(err, "could not write changes")
  1626  	}
  1627  	ldrMgr := leadership.NewLeadershipManager(lease.Manager())
  1628  	return leadershipapiserver.NewLeadershipSettingsAccessor(
  1629  		auth,
  1630  		registerWatcher,
  1631  		getSettings,
  1632  		writeSettings,
  1633  		ldrMgr.Leader,
  1634  	)
  1635  }