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 }