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