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