github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/instancepoller/instancepoller.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package instancepoller
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/names"
    10  
    11  	"github.com/juju/juju/apiserver/common"
    12  	"github.com/juju/juju/apiserver/params"
    13  	"github.com/juju/juju/state"
    14  	"github.com/juju/juju/status"
    15  )
    16  
    17  func init() {
    18  	common.RegisterStandardFacade("InstancePoller", 2, NewInstancePollerAPI)
    19  }
    20  
    21  // InstancePollerAPI provides access to the InstancePoller API facade.
    22  type InstancePollerAPI struct {
    23  	*common.LifeGetter
    24  	*common.ModelWatcher
    25  	*common.ModelMachinesWatcher
    26  	*common.InstanceIdGetter
    27  	*common.StatusGetter
    28  
    29  	st            StateInterface
    30  	resources     *common.Resources
    31  	authorizer    common.Authorizer
    32  	accessMachine common.GetAuthFunc
    33  }
    34  
    35  // NewInstancePollerAPI creates a new server-side InstancePoller API
    36  // facade.
    37  func NewInstancePollerAPI(
    38  	st *state.State,
    39  	resources *common.Resources,
    40  	authorizer common.Authorizer,
    41  ) (*InstancePollerAPI, error) {
    42  
    43  	if !authorizer.AuthModelManager() {
    44  		// InstancePoller must run as environment manager.
    45  		return nil, common.ErrPerm
    46  	}
    47  	accessMachine := common.AuthFuncForTagKind(names.MachineTagKind)
    48  	sti := getState(st)
    49  
    50  	// Life() is supported for machines.
    51  	lifeGetter := common.NewLifeGetter(
    52  		sti,
    53  		accessMachine,
    54  	)
    55  	// ModelConfig() and WatchForModelConfigChanges() are allowed
    56  	// with unrestriced access.
    57  	modelWatcher := common.NewModelWatcher(
    58  		sti,
    59  		resources,
    60  		authorizer,
    61  	)
    62  	// WatchModelMachines() is allowed with unrestricted access.
    63  	machinesWatcher := common.NewModelMachinesWatcher(
    64  		sti,
    65  		resources,
    66  		authorizer,
    67  	)
    68  	// InstanceId() is supported for machines.
    69  	instanceIdGetter := common.NewInstanceIdGetter(
    70  		sti,
    71  		accessMachine,
    72  	)
    73  	// Status() is supported for machines.
    74  	statusGetter := common.NewStatusGetter(
    75  		sti,
    76  		accessMachine,
    77  	)
    78  
    79  	return &InstancePollerAPI{
    80  		LifeGetter:           lifeGetter,
    81  		ModelWatcher:         modelWatcher,
    82  		ModelMachinesWatcher: machinesWatcher,
    83  		InstanceIdGetter:     instanceIdGetter,
    84  		StatusGetter:         statusGetter,
    85  		st:                   sti,
    86  		resources:            resources,
    87  		authorizer:           authorizer,
    88  		accessMachine:        accessMachine,
    89  	}, nil
    90  }
    91  
    92  func (a *InstancePollerAPI) getOneMachine(tag string, canAccess common.AuthFunc) (StateMachine, error) {
    93  	machineTag, err := names.ParseMachineTag(tag)
    94  	if err != nil {
    95  		return nil, err
    96  	}
    97  	if !canAccess(machineTag) {
    98  		return nil, common.ErrPerm
    99  	}
   100  	entity, err := a.st.FindEntity(machineTag)
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  	machine, ok := entity.(StateMachine)
   105  	if !ok {
   106  		return nil, common.NotSupportedError(
   107  			machineTag, fmt.Sprintf("expected machine, got %T", entity),
   108  		)
   109  	}
   110  	return machine, nil
   111  }
   112  
   113  // ProviderAddresses returns the list of all known provider addresses
   114  // for each given entity. Only machine tags are accepted.
   115  func (a *InstancePollerAPI) ProviderAddresses(args params.Entities) (params.MachineAddressesResults, error) {
   116  	result := params.MachineAddressesResults{
   117  		Results: make([]params.MachineAddressesResult, len(args.Entities)),
   118  	}
   119  	canAccess, err := a.accessMachine()
   120  	if err != nil {
   121  		return result, err
   122  	}
   123  	for i, arg := range args.Entities {
   124  		machine, err := a.getOneMachine(arg.Tag, canAccess)
   125  		if err == nil {
   126  			addrs := machine.ProviderAddresses()
   127  			result.Results[i].Addresses = params.FromNetworkAddresses(addrs)
   128  		}
   129  		result.Results[i].Error = common.ServerError(err)
   130  	}
   131  	return result, nil
   132  }
   133  
   134  // SetProviderAddresses updates the list of known provider addresses
   135  // for each given entity. Only machine tags are accepted.
   136  func (a *InstancePollerAPI) SetProviderAddresses(args params.SetMachinesAddresses) (params.ErrorResults, error) {
   137  	result := params.ErrorResults{
   138  		Results: make([]params.ErrorResult, len(args.MachineAddresses)),
   139  	}
   140  	canAccess, err := a.accessMachine()
   141  	if err != nil {
   142  		return result, err
   143  	}
   144  	for i, arg := range args.MachineAddresses {
   145  		machine, err := a.getOneMachine(arg.Tag, canAccess)
   146  		if err == nil {
   147  			addrsToSet := params.NetworkAddresses(arg.Addresses)
   148  			err = machine.SetProviderAddresses(addrsToSet...)
   149  		}
   150  		result.Results[i].Error = common.ServerError(err)
   151  	}
   152  	return result, nil
   153  }
   154  
   155  // InstanceStatus returns the instance status for each given entity.
   156  // Only machine tags are accepted.
   157  func (a *InstancePollerAPI) InstanceStatus(args params.Entities) (params.StatusResults, error) {
   158  	result := params.StatusResults{
   159  		Results: make([]params.StatusResult, len(args.Entities)),
   160  	}
   161  	canAccess, err := a.accessMachine()
   162  	if err != nil {
   163  		return result, err
   164  	}
   165  	for i, arg := range args.Entities {
   166  		machine, err := a.getOneMachine(arg.Tag, canAccess)
   167  		if err == nil {
   168  			var statusInfo status.StatusInfo
   169  			statusInfo, err = machine.InstanceStatus()
   170  			result.Results[i].Status = statusInfo.Status
   171  			result.Results[i].Info = statusInfo.Message
   172  			result.Results[i].Data = statusInfo.Data
   173  			result.Results[i].Since = statusInfo.Since
   174  		}
   175  		result.Results[i].Error = common.ServerError(err)
   176  	}
   177  	return result, nil
   178  }
   179  
   180  // SetInstanceStatus updates the instance status for each given
   181  // entity. Only machine tags are accepted.
   182  func (a *InstancePollerAPI) SetInstanceStatus(args params.SetStatus) (params.ErrorResults, error) {
   183  	result := params.ErrorResults{
   184  		Results: make([]params.ErrorResult, len(args.Entities)),
   185  	}
   186  	canAccess, err := a.accessMachine()
   187  	if err != nil {
   188  		return result, err
   189  	}
   190  	for i, arg := range args.Entities {
   191  		machine, err := a.getOneMachine(arg.Tag, canAccess)
   192  		if err == nil {
   193  			err = machine.SetInstanceStatus(arg.Status, arg.Info, arg.Data)
   194  		}
   195  		result.Results[i].Error = common.ServerError(err)
   196  	}
   197  	return result, nil
   198  }
   199  
   200  // AreManuallyProvisioned returns whether each given entity is
   201  // manually provisioned or not. Only machine tags are accepted.
   202  func (a *InstancePollerAPI) AreManuallyProvisioned(args params.Entities) (params.BoolResults, error) {
   203  	result := params.BoolResults{
   204  		Results: make([]params.BoolResult, len(args.Entities)),
   205  	}
   206  	canAccess, err := a.accessMachine()
   207  	if err != nil {
   208  		return result, err
   209  	}
   210  	for i, arg := range args.Entities {
   211  		machine, err := a.getOneMachine(arg.Tag, canAccess)
   212  		if err == nil {
   213  			result.Results[i].Result, err = machine.IsManual()
   214  		}
   215  		result.Results[i].Error = common.ServerError(err)
   216  	}
   217  	return result, nil
   218  }