github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/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/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 t, err := names.ParseTag(tag, names.MachineTagKind) 43 if err != nil { 44 // Only machine tags are allowed. 45 return false 46 } 47 id := t.Id() 48 for parentId := state.ParentId(id); parentId != ""; parentId = state.ParentId(parentId) { 49 // Until a top-level machine is reached. 50 if names.NewMachineTag(parentId).String() == authEntityTag { 51 // All containers with the authenticated machine as a 52 // parent are accessible by it. 53 return true 54 } 55 } 56 // Not found authorized machine agent among ancestors of the current one. 57 return false 58 }, nil 59 } 60 61 return &NetworkerAPI{ 62 st: st, 63 authorizer: authorizer, 64 getAuthFunc: getAuthFunc, 65 }, nil 66 } 67 68 func (n *NetworkerAPI) oneMachineInfo(id string) ([]network.Info, error) { 69 machine, err := n.st.Machine(id) 70 if err != nil { 71 return nil, err 72 } 73 ifaces, err := machine.NetworkInterfaces() 74 if err != nil { 75 return nil, err 76 } 77 info := make([]network.Info, len(ifaces)) 78 for i, iface := range ifaces { 79 nw, err := n.st.Network(iface.NetworkName()) 80 if err != nil { 81 return nil, err 82 } 83 info[i] = network.Info{ 84 MACAddress: iface.MACAddress(), 85 CIDR: nw.CIDR(), 86 NetworkName: iface.NetworkName(), 87 ProviderId: nw.ProviderId(), 88 VLANTag: nw.VLANTag(), 89 InterfaceName: iface.RawInterfaceName(), 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 var tag names.Tag 105 for i, entity := range args.Entities { 106 if !canAccess(entity.Tag) { 107 err = common.ErrPerm 108 } else { 109 tag, err = names.ParseTag(entity.Tag, names.MachineTagKind) 110 if err == nil { 111 id := tag.Id() 112 result.Results[i].Info, err = n.oneMachineInfo(id) 113 } 114 } 115 result.Results[i].Error = common.ServerError(err) 116 } 117 return result, nil 118 }