github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/state/apiserver/networker/networker.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package networker
     5  
     6  import (
     7  	"github.com/juju/loggo"
     8  	"github.com/juju/names"
     9  
    10  	"github.com/juju/juju/environs/network"
    11  	"github.com/juju/juju/state"
    12  	"github.com/juju/juju/state/api/params"
    13  	"github.com/juju/juju/state/apiserver/common"
    14  )
    15  
    16  var logger = loggo.GetLogger("juju.state.apiserver.networker")
    17  
    18  // NetworkerAPI provides access to the Networker API facade.
    19  type NetworkerAPI struct {
    20  	st          *state.State
    21  	authorizer  common.Authorizer
    22  	getAuthFunc common.GetAuthFunc
    23  }
    24  
    25  // NewNetworkerAPI creates a new client-side Networker API facade.
    26  func NewNetworkerAPI(
    27  	st *state.State,
    28  	_ *common.Resources,
    29  	authorizer common.Authorizer,
    30  ) (*NetworkerAPI, error) {
    31  	if !authorizer.AuthMachineAgent() {
    32  		return nil, common.ErrPerm
    33  	}
    34  	getAuthFunc := func() (common.AuthFunc, error) {
    35  		authEntityTag := authorizer.GetAuthTag()
    36  
    37  		return func(tag string) bool {
    38  			if tag == authEntityTag {
    39  				// A machine agent can always access its own machine.
    40  				return true
    41  			}
    42  			_, id, err := names.ParseTag(tag, names.MachineTagKind)
    43  			if err != nil {
    44  				// Only machine tags are allowed.
    45  				return false
    46  			}
    47  			for parentId := state.ParentId(id); parentId != ""; parentId = state.ParentId(parentId) {
    48  				// Until a top-level machine is reached.
    49  				if names.MachineTag(parentId) == authEntityTag {
    50  					// All containers with the authenticated machine as a
    51  					// parent are accessible by it.
    52  					return true
    53  				}
    54  			}
    55  			// Not found authorized machine agent among ancestors of the current one.
    56  			return false
    57  		}, nil
    58  	}
    59  
    60  	return &NetworkerAPI{
    61  		st:          st,
    62  		authorizer:  authorizer,
    63  		getAuthFunc: getAuthFunc,
    64  	}, nil
    65  }
    66  
    67  func (n *NetworkerAPI) oneMachineInfo(id string) ([]network.Info, error) {
    68  	machine, err := n.st.Machine(id)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	ifaces, err := machine.NetworkInterfaces()
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	info := make([]network.Info, len(ifaces))
    77  	for i, iface := range ifaces {
    78  		nw, err := n.st.Network(iface.NetworkName())
    79  		if err != nil {
    80  			return nil, err
    81  		}
    82  		info[i] = network.Info{
    83  			MACAddress:    iface.MACAddress(),
    84  			CIDR:          nw.CIDR(),
    85  			NetworkName:   iface.NetworkName(),
    86  			ProviderId:    nw.ProviderId(),
    87  			VLANTag:       nw.VLANTag(),
    88  			InterfaceName: iface.RawInterfaceName(),
    89  			IsVirtual:     iface.IsVirtual(),
    90  		}
    91  	}
    92  	return info, nil
    93  }
    94  
    95  // Networks returns the list of networks with related interfaces for a given set of machines.
    96  func (n *NetworkerAPI) MachineNetworkInfo(args params.Entities) (params.MachineNetworkInfoResults, error) {
    97  	result := params.MachineNetworkInfoResults{
    98  		Results: make([]params.MachineNetworkInfoResult, len(args.Entities)),
    99  	}
   100  	canAccess, err := n.getAuthFunc()
   101  	if err != nil {
   102  		return result, err
   103  	}
   104  	id := ""
   105  	for i, entity := range args.Entities {
   106  		if !canAccess(entity.Tag) {
   107  			err = common.ErrPerm
   108  		} else {
   109  			_, id, err = names.ParseTag(entity.Tag, names.MachineTagKind)
   110  			if err == nil {
   111  				result.Results[i].Info, err = n.oneMachineInfo(id)
   112  			}
   113  		}
   114  		result.Results[i].Error = common.ServerError(err)
   115  	}
   116  	return result, nil
   117  }