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

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // The machiner package implements the API interface
     5  // used by the machiner worker.
     6  package machine
     7  
     8  import (
     9  	"github.com/juju/errors"
    10  	"github.com/juju/loggo"
    11  	"github.com/juju/names"
    12  
    13  	"github.com/juju/juju/apiserver/common"
    14  	"github.com/juju/juju/apiserver/common/networkingcommon"
    15  	"github.com/juju/juju/apiserver/params"
    16  	"github.com/juju/juju/state"
    17  	"github.com/juju/juju/state/multiwatcher"
    18  )
    19  
    20  var logger = loggo.GetLogger("juju.apiserver.machine")
    21  
    22  func init() {
    23  	common.RegisterStandardFacade("Machiner", 1, NewMachinerAPI)
    24  }
    25  
    26  // MachinerAPI implements the API used by the machiner worker.
    27  type MachinerAPI struct {
    28  	*common.LifeGetter
    29  	*common.StatusSetter
    30  	*common.DeadEnsurer
    31  	*common.AgentEntityWatcher
    32  	*common.APIAddresser
    33  
    34  	st           *state.State
    35  	auth         common.Authorizer
    36  	getCanModify common.GetAuthFunc
    37  	getCanRead   common.GetAuthFunc
    38  }
    39  
    40  // NewMachinerAPI creates a new instance of the Machiner API.
    41  func NewMachinerAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*MachinerAPI, error) {
    42  	if !authorizer.AuthMachineAgent() {
    43  		return nil, common.ErrPerm
    44  	}
    45  	getCanModify := func() (common.AuthFunc, error) {
    46  		return authorizer.AuthOwner, nil
    47  	}
    48  	getCanRead := func() (common.AuthFunc, error) {
    49  		return authorizer.AuthOwner, nil
    50  	}
    51  	return &MachinerAPI{
    52  		LifeGetter:         common.NewLifeGetter(st, getCanRead),
    53  		StatusSetter:       common.NewStatusSetter(st, getCanModify),
    54  		DeadEnsurer:        common.NewDeadEnsurer(st, getCanModify),
    55  		AgentEntityWatcher: common.NewAgentEntityWatcher(st, resources, getCanRead),
    56  		APIAddresser:       common.NewAPIAddresser(st, resources),
    57  		st:                 st,
    58  		auth:               authorizer,
    59  		getCanModify:       getCanModify,
    60  		getCanRead:         getCanRead,
    61  	}, nil
    62  }
    63  
    64  func (api *MachinerAPI) getMachine(tag names.Tag) (*state.Machine, error) {
    65  	entity, err := api.st.FindEntity(tag)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	return entity.(*state.Machine), nil
    70  }
    71  
    72  func (api *MachinerAPI) SetMachineAddresses(args params.SetMachinesAddresses) (params.ErrorResults, error) {
    73  	results := params.ErrorResults{
    74  		Results: make([]params.ErrorResult, len(args.MachineAddresses)),
    75  	}
    76  	canModify, err := api.getCanModify()
    77  	if err != nil {
    78  		return results, err
    79  	}
    80  	for i, arg := range args.MachineAddresses {
    81  		tag, err := names.ParseMachineTag(arg.Tag)
    82  		if err != nil {
    83  			results.Results[i].Error = common.ServerError(common.ErrPerm)
    84  			continue
    85  		}
    86  		err = common.ErrPerm
    87  		if canModify(tag) {
    88  			var m *state.Machine
    89  			m, err = api.getMachine(tag)
    90  			if err == nil {
    91  				addresses := params.NetworkAddresses(arg.Addresses)
    92  				err = m.SetMachineAddresses(addresses...)
    93  			} else if errors.IsNotFound(err) {
    94  				err = common.ErrPerm
    95  			}
    96  		}
    97  		results.Results[i].Error = common.ServerError(err)
    98  	}
    99  	return results, nil
   100  }
   101  
   102  // Jobs returns the jobs assigned to the given entities.
   103  func (api *MachinerAPI) Jobs(args params.Entities) (params.JobsResults, error) {
   104  	result := params.JobsResults{
   105  		Results: make([]params.JobsResult, len(args.Entities)),
   106  	}
   107  
   108  	canRead, err := api.getCanRead()
   109  	if err != nil {
   110  		return result, err
   111  	}
   112  
   113  	for i, agent := range args.Entities {
   114  		tag, err := names.ParseMachineTag(agent.Tag)
   115  		if err != nil {
   116  			result.Results[i].Error = common.ServerError(err)
   117  			continue
   118  		}
   119  
   120  		if !canRead(tag) {
   121  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   122  			continue
   123  		}
   124  
   125  		machine, err := api.getMachine(tag)
   126  		if err != nil {
   127  			result.Results[i].Error = common.ServerError(err)
   128  			continue
   129  		}
   130  		machineJobs := machine.Jobs()
   131  		jobs := make([]multiwatcher.MachineJob, len(machineJobs))
   132  		for i, job := range machineJobs {
   133  			jobs[i] = job.ToParams()
   134  		}
   135  		result.Results[i].Jobs = jobs
   136  	}
   137  	return result, nil
   138  }
   139  
   140  func (api *MachinerAPI) SetObservedNetworkConfig(args params.SetMachineNetworkConfig) error {
   141  	m, err := api.getMachineForSettingNetworkConfig(args.Tag)
   142  	if err != nil {
   143  		return errors.Trace(err)
   144  	}
   145  	if m.IsContainer() {
   146  		return nil
   147  	}
   148  	observedConfig := args.Config
   149  	logger.Tracef("observed network config of machine %q: %+v", m.Id(), observedConfig)
   150  	if len(observedConfig) == 0 {
   151  		logger.Infof("not updating machine network config: no observed network config found")
   152  		return nil
   153  	}
   154  
   155  	providerConfig, err := api.getOneMachineProviderNetworkConfig(m)
   156  	if errors.IsNotProvisioned(err) {
   157  		logger.Infof("not updating provider network config: %v", err)
   158  		return nil
   159  	} else if err != nil {
   160  		return errors.Trace(err)
   161  	}
   162  	if len(providerConfig) == 0 {
   163  		logger.Infof("not updating machine network config: no provider network config found")
   164  		return nil
   165  	}
   166  
   167  	mergedConfig := networkingcommon.MergeProviderAndObservedNetworkConfigs(providerConfig, observedConfig)
   168  	logger.Tracef("merged observed and provider network config: %+v", mergedConfig)
   169  
   170  	return api.setOneMachineNetworkConfig(m, mergedConfig)
   171  }
   172  
   173  func (api *MachinerAPI) getMachineForSettingNetworkConfig(machineTag string) (*state.Machine, error) {
   174  	canModify, err := api.getCanModify()
   175  	if err != nil {
   176  		return nil, errors.Trace(err)
   177  	}
   178  
   179  	tag, err := names.ParseMachineTag(machineTag)
   180  	if err != nil {
   181  		return nil, errors.Trace(err)
   182  	}
   183  	if !canModify(tag) {
   184  		return nil, errors.Trace(common.ErrPerm)
   185  	}
   186  
   187  	m, err := api.getMachine(tag)
   188  	if errors.IsNotFound(err) {
   189  		return nil, errors.Trace(common.ErrPerm)
   190  	} else if err != nil {
   191  		return nil, errors.Trace(err)
   192  	}
   193  
   194  	if m.IsContainer() {
   195  		logger.Warningf("not updating network config for container %q", m.Id())
   196  	}
   197  
   198  	return m, nil
   199  }
   200  
   201  func (api *MachinerAPI) setOneMachineNetworkConfig(m *state.Machine, networkConfig []params.NetworkConfig) error {
   202  	devicesArgs, devicesAddrs := networkingcommon.NetworkConfigsToStateArgs(networkConfig)
   203  
   204  	logger.Debugf("setting devices: %+v", devicesArgs)
   205  	if err := m.SetParentLinkLayerDevicesBeforeTheirChildren(devicesArgs); err != nil {
   206  		return errors.Trace(err)
   207  	}
   208  
   209  	logger.Debugf("setting addresses: %+v", devicesAddrs)
   210  	if err := m.SetDevicesAddressesIdempotently(devicesAddrs); err != nil {
   211  		return errors.Trace(err)
   212  	}
   213  
   214  	logger.Debugf("updated machine %q network config", m.Id())
   215  	return nil
   216  }
   217  
   218  func (api *MachinerAPI) SetProviderNetworkConfig(args params.Entities) (params.ErrorResults, error) {
   219  	result := params.ErrorResults{
   220  		Results: make([]params.ErrorResult, len(args.Entities)),
   221  	}
   222  
   223  	for i, arg := range args.Entities {
   224  		m, err := api.getMachineForSettingNetworkConfig(arg.Tag)
   225  		if err != nil {
   226  			result.Results[i].Error = common.ServerError(err)
   227  			continue
   228  		}
   229  
   230  		if m.IsContainer() {
   231  			continue
   232  		}
   233  
   234  		providerConfig, err := api.getOneMachineProviderNetworkConfig(m)
   235  		if err != nil {
   236  			result.Results[i].Error = common.ServerError(err)
   237  			continue
   238  		} else if len(providerConfig) == 0 {
   239  			continue
   240  		}
   241  
   242  		sortedProviderConfig := networkingcommon.SortNetworkConfigsByParents(providerConfig)
   243  		logger.Tracef("sorted provider network config for %q: %+v", m.Id(), sortedProviderConfig)
   244  
   245  		if err := api.setOneMachineNetworkConfig(m, sortedProviderConfig); err != nil {
   246  			result.Results[i].Error = common.ServerError(err)
   247  			continue
   248  		}
   249  	}
   250  	return result, nil
   251  }
   252  
   253  func (api *MachinerAPI) getOneMachineProviderNetworkConfig(m *state.Machine) ([]params.NetworkConfig, error) {
   254  	instId, err := m.InstanceId()
   255  	if err != nil {
   256  		return nil, errors.Trace(err)
   257  	}
   258  
   259  	netEnviron, err := networkingcommon.NetworkingEnvironFromModelConfig(api.st)
   260  	if errors.IsNotSupported(err) {
   261  		logger.Infof("not updating provider network config: %v", err)
   262  		return nil, nil
   263  	} else if err != nil {
   264  		return nil, errors.Annotate(err, "cannot get provider network config")
   265  	}
   266  
   267  	interfaceInfos, err := netEnviron.NetworkInterfaces(instId)
   268  	if err != nil {
   269  		return nil, errors.Annotatef(err, "cannot get network interfaces of %q", instId)
   270  	}
   271  	if len(interfaceInfos) == 0 {
   272  		logger.Infof("not updating provider network config: no interfaces returned")
   273  		return nil, nil
   274  	}
   275  
   276  	providerConfig := networkingcommon.NetworkConfigFromInterfaceInfo(interfaceInfos)
   277  	logger.Tracef("provider network config instance %q: %+v", instId, providerConfig)
   278  
   279  	return providerConfig, nil
   280  }