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 }