Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(447)

Delta Between Two Patch Sets: state/apiserver/provisioner/provisioner.go

Issue 75250043: Add DistributionGroup to StartInstanceParams
Left Patch Set: Add DistributionInstances to StartInstanceParams Created 10 years ago
Right Patch Set: Add DistributionGroup to StartInstanceParams Created 9 years, 12 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « state/api/provisioner/provisioner_test.go ('k') | state/apiserver/provisioner/provisioner_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2012, 2013 Canonical Ltd. 1 // Copyright 2012, 2013 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details. 2 // Licensed under the AGPLv3, see LICENCE file for details.
3 3
4 package provisioner 4 package provisioner
5 5
6 import ( 6 import (
7 "launchpad.net/juju-core/constraints" 7 "launchpad.net/juju-core/constraints"
8 "launchpad.net/juju-core/instance" 8 "launchpad.net/juju-core/instance"
9 "launchpad.net/juju-core/names" 9 "launchpad.net/juju-core/names"
10 "launchpad.net/juju-core/state" 10 "launchpad.net/juju-core/state"
(...skipping 10 matching lines...) Expand all
21 *common.DeadEnsurer 21 *common.DeadEnsurer
22 *common.PasswordChanger 22 *common.PasswordChanger
23 *common.LifeGetter 23 *common.LifeGetter
24 *common.StateAddresser 24 *common.StateAddresser
25 *common.APIAddresser 25 *common.APIAddresser
26 *common.ToolsGetter 26 *common.ToolsGetter
27 *common.EnvironWatcher 27 *common.EnvironWatcher
28 *common.EnvironMachinesWatcher 28 *common.EnvironMachinesWatcher
29 *common.InstanceIdGetter 29 *common.InstanceIdGetter
30 30
31 » st *state.State 31 » st *state.State
32 » resources *common.Resources 32 » resources *common.Resources
33 » authorizer common.Authorizer 33 » authorizer common.Authorizer
34 » getAuthFunc common.GetAuthFunc 34 » getAuthFunc common.GetAuthFunc
35 » getCanWatchMachines common.GetAuthFunc
35 } 36 }
36 37
37 // NewProvisionerAPI creates a new server-side ProvisionerAPI facade. 38 // NewProvisionerAPI creates a new server-side ProvisionerAPI facade.
38 func NewProvisionerAPI( 39 func NewProvisionerAPI(
39 st *state.State, 40 st *state.State,
40 resources *common.Resources, 41 resources *common.Resources,
41 authorizer common.Authorizer, 42 authorizer common.Authorizer,
42 ) (*ProvisionerAPI, error) { 43 ) (*ProvisionerAPI, error) {
43 if !authorizer.AuthMachineAgent() && !authorizer.AuthEnvironManager() { 44 if !authorizer.AuthMachineAgent() && !authorizer.AuthEnvironManager() {
44 return nil, common.ErrPerm 45 return nil, common.ErrPerm
(...skipping 27 matching lines...) Expand all
72 getCanWatch := common.AuthAlways(true) 73 getCanWatch := common.AuthAlways(true)
73 // Only the environment provisioner can read secrets. 74 // Only the environment provisioner can read secrets.
74 getCanReadSecrets := common.AuthAlways(authorizer.AuthEnvironManager()) 75 getCanReadSecrets := common.AuthAlways(authorizer.AuthEnvironManager())
75 return &ProvisionerAPI{ 76 return &ProvisionerAPI{
76 Remover: common.NewRemover(st, false, getAuthFunc ), 77 Remover: common.NewRemover(st, false, getAuthFunc ),
77 StatusSetter: common.NewStatusSetter(st, getAuthFunc), 78 StatusSetter: common.NewStatusSetter(st, getAuthFunc),
78 DeadEnsurer: common.NewDeadEnsurer(st, getAuthFunc), 79 DeadEnsurer: common.NewDeadEnsurer(st, getAuthFunc),
79 PasswordChanger: common.NewPasswordChanger(st, getAuthFun c), 80 PasswordChanger: common.NewPasswordChanger(st, getAuthFun c),
80 LifeGetter: common.NewLifeGetter(st, getAuthFunc), 81 LifeGetter: common.NewLifeGetter(st, getAuthFunc),
81 StateAddresser: common.NewStateAddresser(st), 82 StateAddresser: common.NewStateAddresser(st),
82 » » APIAddresser: common.NewAPIAddresser(st), 83 » » APIAddresser: common.NewAPIAddresser(st, resources),
83 ToolsGetter: common.NewToolsGetter(st, getAuthFunc), 84 ToolsGetter: common.NewToolsGetter(st, getAuthFunc),
84 EnvironWatcher: common.NewEnvironWatcher(st, resources, getCanWatch, getCanReadSecrets), 85 EnvironWatcher: common.NewEnvironWatcher(st, resources, getCanWatch, getCanReadSecrets),
85 EnvironMachinesWatcher: common.NewEnvironMachinesWatcher(st, res ources, getCanReadSecrets), 86 EnvironMachinesWatcher: common.NewEnvironMachinesWatcher(st, res ources, getCanReadSecrets),
86 InstanceIdGetter: common.NewInstanceIdGetter(st, getAuthFu nc), 87 InstanceIdGetter: common.NewInstanceIdGetter(st, getAuthFu nc),
87 st: st, 88 st: st,
88 resources: resources, 89 resources: resources,
89 authorizer: authorizer, 90 authorizer: authorizer,
90 getAuthFunc: getAuthFunc, 91 getAuthFunc: getAuthFunc,
92 getCanWatchMachines: getCanReadSecrets,
91 }, nil 93 }, nil
92 } 94 }
93 95
94 func (p *ProvisionerAPI) getMachine(canAccess common.AuthFunc, tag string) (*sta te.Machine, error) { 96 func (p *ProvisionerAPI) getMachine(canAccess common.AuthFunc, tag string) (*sta te.Machine, error) {
95 if !canAccess(tag) { 97 if !canAccess(tag) {
96 return nil, common.ErrPerm 98 return nil, common.ErrPerm
97 } 99 }
98 entity, err := p.st.FindEntity(tag) 100 entity, err := p.st.FindEntity(tag)
99 if err != nil { 101 if err != nil {
100 return nil, err 102 return nil, err
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 Results: make([]params.StatusResult, len(args.Entities)), 210 Results: make([]params.StatusResult, len(args.Entities)),
209 } 211 }
210 canAccess, err := p.getAuthFunc() 212 canAccess, err := p.getAuthFunc()
211 if err != nil { 213 if err != nil {
212 return result, err 214 return result, err
213 } 215 }
214 for i, entity := range args.Entities { 216 for i, entity := range args.Entities {
215 machine, err := p.getMachine(canAccess, entity.Tag) 217 machine, err := p.getMachine(canAccess, entity.Tag)
216 if err == nil { 218 if err == nil {
217 r := &result.Results[i] 219 r := &result.Results[i]
218 » » » r.Status, r.Info, _, err = machine.Status() 220 » » » r.Status, r.Info, r.Data, err = machine.Status()
219 » » } 221 » » }
220 » » result.Results[i].Error = common.ServerError(err) 222 » » result.Results[i].Error = common.ServerError(err)
221 » } 223 » }
222 » return result, nil 224 » return result, nil
225 }
226
227 // MachinesWithTransientErrors returns status data for machines with provisionin g
228 // errors which are transient.
229 func (p *ProvisionerAPI) MachinesWithTransientErrors() (params.StatusResults, er ror) {
230 » results := params.StatusResults{}
231 » canAccessFunc, err := p.getAuthFunc()
232 » if err != nil {
233 » » return results, err
234 » }
235 » // TODO (wallyworld) - add state.State API for more efficient machines q uery
236 » machines, err := p.st.AllMachines()
237 » if err != nil {
238 » » return results, err
239 » }
240 » for _, machine := range machines {
241 » » if !canAccessFunc(machine.Tag()) {
242 » » » continue
243 » » }
244 » » if _, provisionedErr := machine.InstanceId(); provisionedErr == nil {
245 » » » // Machine may have been provisioned but machiner hasn't set the
246 » » » // status to Started yet.
247 » » » continue
248 » » }
249 » » result := params.StatusResult{}
250 » » if result.Status, result.Info, result.Data, err = machine.Status (); err != nil {
251 » » » continue
252 » » }
253 » » if result.Status != params.StatusError {
254 » » » continue
255 » » }
256 » » // Transient errors are marked as such in the status data.
257 » » if transient, ok := result.Data["transient"].(bool); !ok || !tra nsient {
258 » » » continue
259 » » }
260 » » result.Id = machine.Id()
261 » » result.Life = params.Life(machine.Life().String())
262 » » results.Results = append(results.Results, result)
263 » }
264 » return results, nil
223 } 265 }
224 266
225 // Series returns the deployed series for each given machine entity. 267 // Series returns the deployed series for each given machine entity.
226 func (p *ProvisionerAPI) Series(args params.Entities) (params.StringResults, err or) { 268 func (p *ProvisionerAPI) Series(args params.Entities) (params.StringResults, err or) {
227 result := params.StringResults{ 269 result := params.StringResults{
228 Results: make([]params.StringResult, len(args.Entities)), 270 Results: make([]params.StringResult, len(args.Entities)),
229 } 271 }
230 canAccess, err := p.getAuthFunc() 272 canAccess, err := p.getAuthFunc()
231 if err != nil { 273 if err != nil {
232 return result, err 274 return result, err
233 } 275 }
234 for i, entity := range args.Entities { 276 for i, entity := range args.Entities {
235 machine, err := p.getMachine(canAccess, entity.Tag) 277 machine, err := p.getMachine(canAccess, entity.Tag)
236 if err == nil { 278 if err == nil {
237 result.Results[i].Result = machine.Series() 279 result.Results[i].Result = machine.Series()
238 } 280 }
239 result.Results[i].Error = common.ServerError(err) 281 result.Results[i].Error = common.ServerError(err)
240 } 282 }
241 return result, nil 283 return result, nil
242 } 284 }
243 285
244 // CommonServiceInstances returns, for each given machine entity, 286 // DistributionGroup returns, for each given machine entity,
245 // the instances that contain units of the services deployed to 287 // a slice of instance.Ids that belong to the same distribution
246 // that machine. 288 // group as that machine. This information may be used to
247 func (p *ProvisionerAPI) CommonServiceInstances(args params.Entities) (params.Co mmonServiceInstancesResults, error) { 289 // distribute instances for high availability.
248 » result := params.CommonServiceInstancesResults{ 290 func (p *ProvisionerAPI) DistributionGroup(args params.Entities) (params.Distrib utionGroupResults, error) {
249 » » Results: make([]params.CommonServiceInstancesResult, len(args.En tities)), 291 » result := params.DistributionGroupResults{
250 » } 292 » » Results: make([]params.DistributionGroupResult, len(args.Entitie s)),
251 » canAccess, err := p.getAuthFunc() 293 » }
252 » if err != nil { 294 » canAccess, err := p.getAuthFunc()
253 » » return result, err 295 » if err != nil {
254 » } 296 » » return result, err
255 297 » }
256 » cache := make(map[string][]instance.Id) // service -> []instance.Id 298 » for i, entity := range args.Entities {
257 » getInstanceIds := func(m *state.Machine) ([]instance.Id, error) { 299 » » machine, err := p.getMachine(canAccess, entity.Tag)
258 » » units, err := m.Units() 300 » » if err == nil {
301 » » » // If the machine is an environment manager, return
302 » » » // environment manager instances. Otherwise, return
303 » » » // instances with services in common with the machine
304 » » » // being provisioned.
305 » » » if machine.IsManager() {
306 » » » » result.Results[i].Result, err = environManagerIn stances(p.st)
307 » » » } else {
308 » » » » result.Results[i].Result, err = commonServiceIns tances(p.st, machine)
309 » » » }
310 » » }
311 » » result.Results[i].Error = common.ServerError(err)
312 » }
313 » return result, nil
314 }
315
316 // environManagerInstances returns all environ manager instances.
317 func environManagerInstances(st *state.State) ([]instance.Id, error) {
318 » info, err := st.StateServerInfo()
319 » if err != nil {
320 » » return nil, err
321 » }
322 » instances := make([]instance.Id, 0, len(info.MachineIds))
323 » for _, id := range info.MachineIds {
324 » » machine, err := st.Machine(id)
259 if err != nil { 325 if err != nil {
260 return nil, err 326 return nil, err
261 } 327 }
262 » » var instanceIdSet set.Strings 328 » » instanceId, err := machine.InstanceId()
263 » » for _, unit := range units { 329 » » if err == nil {
264 » » » if !unit.IsPrincipal() { 330 » » » instances = append(instances, instanceId)
331 » » } else if !state.IsNotProvisionedError(err) {
332 » » » return nil, err
333 » » }
334 » }
335 » return instances, nil
336 }
337
338 // commonServiceInstances returns instances with
339 // services in common with the specified machine.
340 func commonServiceInstances(st *state.State, m *state.Machine) ([]instance.Id, e rror) {
341 » units, err := m.Units()
342 » if err != nil {
343 » » return nil, err
344 » }
345 » var instanceIdSet set.Strings
346 » for _, unit := range units {
347 » » if !unit.IsPrincipal() {
348 » » » continue
349 » » }
350 » » service, err := unit.Service()
351 » » if err != nil {
352 » » » return nil, err
353 » » }
354 » » allUnits, err := service.AllUnits()
355 » » if err != nil {
356 » » » return nil, err
357 » » }
358 » » for _, unit := range allUnits {
359 » » » machineId, err := unit.AssignedMachineId()
360 » » » if state.IsNotAssigned(err) {
265 continue 361 continue
266 » » » } 362 » » » } else if err != nil {
267 » » » service, err := unit.Service() 363 » » » » return nil, err
364 » » » }
365 » » » machine, err := st.Machine(machineId)
268 if err != nil { 366 if err != nil {
269 return nil, err 367 return nil, err
270 } 368 }
271 » » » instanceIds, ok := cache[service.Name()] 369 » » » instanceId, err := machine.InstanceId()
272 » » » if !ok { 370 » » » if err == nil {
273 » » » » allUnits, err := service.AllUnits()
274 » » » » if err != nil {
275 » » » » » return nil, err
276 » » » » }
277 » » » » for _, unit := range allUnits {
278 » » » » » machineId, err := unit.AssignedMachineId ()
279 » » » » » if state.IsNotAssigned(err) {
280 » » » » » » continue
281 » » » » » } else if err != nil {
282 » » » » » » return nil, err
283 » » » » » }
284 » » » » » machine, err := p.st.Machine(machineId)
285 » » » » » if err != nil {
286 » » » » » » return nil, err
287 » » » » » }
288 » » » » » instanceId, err := machine.InstanceId()
289 » » » » » if err == nil {
290 » » » » » » instanceIds = append(instanceIds , instanceId)
291 » » » » » } else if state.IsNotProvisionedError(er r) {
292 » » » » » » continue
293 » » » » » } else {
294 » » » » » » return nil, err
295 » » » » » }
296 » » » » }
297 » » » » cache[service.Name()] = instanceIds
298 » » » }
299 » » » for _, instanceId := range instanceIds {
300 instanceIdSet.Add(string(instanceId)) 371 instanceIdSet.Add(string(instanceId))
301 » » » } 372 » » » } else if state.IsNotProvisionedError(err) {
302 » » } 373 » » » » continue
303 » » instanceIds := make([]instance.Id, instanceIdSet.Size()) 374 » » » } else {
304 » » // Sort values to simplify testing. 375 » » » » return nil, err
305 » » for i, instanceId := range instanceIdSet.SortedValues() { 376 » » » }
306 » » » instanceIds[i] = instance.Id(instanceId) 377 » » }
307 » » } 378 » }
308 » » return instanceIds, nil 379 » instanceIds := make([]instance.Id, instanceIdSet.Size())
309 » } 380 » // Sort values to simplify testing.
310 381 » for i, instanceId := range instanceIdSet.SortedValues() {
311 » for i, entity := range args.Entities { 382 » » instanceIds[i] = instance.Id(instanceId)
312 » » machine, err := p.getMachine(canAccess, entity.Tag) 383 » }
313 » » if err == nil { 384 » return instanceIds, nil
314 » » » result.Results[i].Result, err = getInstanceIds(machine)
315 » » }
316 » » result.Results[i].Error = common.ServerError(err)
317 » }
318 » return result, nil
319 } 385 }
320 386
321 // Constraints returns the constraints for each given machine entity. 387 // Constraints returns the constraints for each given machine entity.
322 func (p *ProvisionerAPI) Constraints(args params.Entities) (params.ConstraintsRe sults, error) { 388 func (p *ProvisionerAPI) Constraints(args params.Entities) (params.ConstraintsRe sults, error) {
323 result := params.ConstraintsResults{ 389 result := params.ConstraintsResults{
324 Results: make([]params.ConstraintsResult, len(args.Entities)), 390 Results: make([]params.ConstraintsResult, len(args.Entities)),
325 } 391 }
326 canAccess, err := p.getAuthFunc() 392 canAccess, err := p.getAuthFunc()
327 if err != nil { 393 if err != nil {
328 return result, err 394 return result, err
329 } 395 }
330 for i, entity := range args.Entities { 396 for i, entity := range args.Entities {
331 machine, err := p.getMachine(canAccess, entity.Tag) 397 machine, err := p.getMachine(canAccess, entity.Tag)
332 if err == nil { 398 if err == nil {
333 var cons constraints.Value 399 var cons constraints.Value
334 cons, err = machine.Constraints() 400 cons, err = machine.Constraints()
335 if err == nil { 401 if err == nil {
336 result.Results[i].Constraints = cons 402 result.Results[i].Constraints = cons
403 }
404 }
405 result.Results[i].Error = common.ServerError(err)
406 }
407 return result, nil
408 }
409
410 // Networks returns the networks for each given machine entity.
411 func (p *ProvisionerAPI) Networks(args params.Entities) (params.NetworksResults, error) {
412 result := params.NetworksResults{
413 Results: make([]params.NetworkResult, len(args.Entities)),
414 }
415 canAccess, err := p.getAuthFunc()
416 if err != nil {
417 return result, err
418 }
419 for i, entity := range args.Entities {
420 machine, err := p.getMachine(canAccess, entity.Tag)
421 if err == nil {
422 var includeNetworks []string
423 var excludeNetworks []string
424 includeNetworks, excludeNetworks, err = machine.Networks ()
425 if err == nil {
426 result.Results[i].IncludeNetworks = includeNetwo rks
427 result.Results[i].ExcludeNetworks = excludeNetwo rks
337 } 428 }
338 } 429 }
339 result.Results[i].Error = common.ServerError(err) 430 result.Results[i].Error = common.ServerError(err)
340 } 431 }
341 return result, nil 432 return result, nil
342 } 433 }
343 434
344 // SetProvisioned sets the provider specific machine id, nonce and 435 // SetProvisioned sets the provider specific machine id, nonce and
345 // metadata for each given machine. Once set, the instance id cannot 436 // metadata for each given machine. Once set, the instance id cannot
346 // be changed. 437 // be changed.
347 func (p *ProvisionerAPI) SetProvisioned(args params.SetProvisioned) (params.Erro rResults, error) { 438 func (p *ProvisionerAPI) SetProvisioned(args params.SetProvisioned) (params.Erro rResults, error) {
348 result := params.ErrorResults{ 439 result := params.ErrorResults{
349 Results: make([]params.ErrorResult, len(args.Machines)), 440 Results: make([]params.ErrorResult, len(args.Machines)),
350 } 441 }
351 canAccess, err := p.getAuthFunc() 442 canAccess, err := p.getAuthFunc()
352 if err != nil { 443 if err != nil {
353 return result, err 444 return result, err
354 } 445 }
355 for i, arg := range args.Machines { 446 for i, arg := range args.Machines {
356 machine, err := p.getMachine(canAccess, arg.Tag) 447 machine, err := p.getMachine(canAccess, arg.Tag)
357 if err == nil { 448 if err == nil {
358 err = machine.SetProvisioned(arg.InstanceId, arg.Nonce, arg.Characteristics) 449 err = machine.SetProvisioned(arg.InstanceId, arg.Nonce, arg.Characteristics)
359 } 450 }
360 result.Results[i].Error = common.ServerError(err) 451 result.Results[i].Error = common.ServerError(err)
361 } 452 }
362 return result, nil 453 return result, nil
363 } 454 }
455
456 // WatchMachineErrorRetry returns a NotifyWatcher that notifies when
457 // the provisioner should retry provisioning machines with transient errors.
458 func (p *ProvisionerAPI) WatchMachineErrorRetry() (params.NotifyWatchResult, err or) {
459 result := params.NotifyWatchResult{}
460 canWatch, err := p.getCanWatchMachines()
461 if err != nil {
462 return params.NotifyWatchResult{}, err
463 }
464 if !canWatch("") {
465 return result, common.ErrPerm
466 }
467 watch := newWatchMachineErrorRetry()
468 // Consume any initial event and forward it to the result.
469 if _, ok := <-watch.Changes(); ok {
470 result.NotifyWatcherId = p.resources.Register(watch)
471 } else {
472 return result, watcher.MustErr(watch)
473 }
474 return result, nil
475 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b