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

Delta Between Two Patch Sets: state/unit.go

Issue 6549045: state: implement Unit.AssignToUnusedMachine
Left Patch Set: state: implement Unit.AssignToUnusedMachine Created 12 years, 6 months ago
Right Patch Set: state: implement Unit.AssignToUnusedMachine Created 12 years, 6 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/tools_test.go ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 package state 1 package state
2 2
3 import ( 3 import (
4 "errors" 4 "errors"
5 "fmt" 5 "fmt"
6 "labix.org/v2/mgo/txn" 6 "labix.org/v2/mgo/txn"
7 "launchpad.net/juju-core/charm" 7 "launchpad.net/juju-core/charm"
8 "launchpad.net/juju-core/state/presence" 8 "launchpad.net/juju-core/state/presence"
9 "launchpad.net/juju-core/trivial" 9 "launchpad.net/juju-core/trivial"
10 "sort" 10 "sort"
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 } 393 }
394 if pudoc.MachineId == nil { 394 if pudoc.MachineId == nil {
395 return 0, errors.New("unit not assigned to machine") 395 return 0, errors.New("unit not assigned to machine")
396 } 396 }
397 return *pudoc.MachineId, nil 397 return *pudoc.MachineId, nil
398 } 398 }
399 399
400 var ( 400 var (
401 machineDeadErr = errors.New("machine is dead") 401 machineDeadErr = errors.New("machine is dead")
402 unitDeadErr = errors.New("unit is dead") 402 unitDeadErr = errors.New("unit is dead")
403 cannotAssignErr = errors.New("unit cannot be assigned to machine")
niemeyer 2012/09/20 17:15:37 This seems confusing, and luckily seems unused as
rog 2012/09/21 08:35:19 Done.
404 alreadyAssignedErr = errors.New("unit is already assigned to a machine") 403 alreadyAssignedErr = errors.New("unit is already assigned to a machine")
405 » notUnusedErr = errors.New("machine is not unused") 404 » inUseErr = errors.New("machine is not unused")
niemeyer 2012/09/20 17:15:37 inUseErr = "machine is in use"
niemeyer 2012/09/21 09:28:13 This was just half-done. Still has a double-negati
406 ) 405 )
407 406
408 // assignToMachine is the internal version of AssignToMachine, 407 // assignToMachine is the internal version of AssignToMachine,
409 // also used by AssignToUnusedMachine. It returns specific errors 408 // also used by AssignToUnusedMachine. It returns specific errors
410 // in some cases: 409 // in some cases:
411 // - machineDeadErr when the machine is not alive. 410 // - machineDeadErr when the machine is not alive.
412 // - unitDeadErr when the unit is not alive. 411 // - unitDeadErr when the unit is not alive.
413 // - alreadyAssignedErr when the unit has already been assigned 412 // - alreadyAssignedErr when the unit has already been assigned
414 // - notUnusedErr when the machine already has a unit assigned (if onlyIfUnused is true) 413 // - inUseErr when the machine already has a unit assigned (if unused is true)
415 func (u *Unit) assignToMachine(m *Machine, onlyIfUnused bool) (err error) { 414 func (u *Unit) assignToMachine(m *Machine, unused bool) (err error) {
niemeyer 2012/09/20 17:15:37 s/onlyIfUnused/unused/
rog 2012/09/21 08:35:19 much better.
416 if u.doc.MachineId != nil { 415 if u.doc.MachineId != nil {
417 if *u.doc.MachineId != m.Id() { 416 if *u.doc.MachineId != m.Id() {
418 return alreadyAssignedErr 417 return alreadyAssignedErr
419 } 418 }
420 return nil 419 return nil
421 } 420 }
422 if u.doc.Principal != "" { 421 if u.doc.Principal != "" {
423 return fmt.Errorf("unit is a subordinate") 422 return fmt.Errorf("unit is a subordinate")
424 } 423 }
425 assert := append(isAlive, D{ 424 assert := append(isAlive, D{
426 {"$or", []D{ 425 {"$or", []D{
427 D{{"machineid", nil}}, 426 D{{"machineid", nil}},
428 D{{"machineid", m.Id()}}, 427 D{{"machineid", m.Id()}},
429 }}, 428 }},
430 }...) 429 }...)
431 massert := isAlive 430 massert := isAlive
432 » if onlyIfUnused { 431 » if unused {
433 massert = append(massert, D{{"principals", D{{"$size", 0}}}}...) 432 massert = append(massert, D{{"principals", D{{"$size", 0}}}}...)
434 } 433 }
435 ops := []txn.Op{{ 434 ops := []txn.Op{{
436 C: u.st.units.Name, 435 C: u.st.units.Name,
437 Id: u.doc.Name, 436 Id: u.doc.Name,
438 Assert: assert, 437 Assert: assert,
439 Update: D{{"$set", D{{"machineid", m.doc.Id}}}}, 438 Update: D{{"$set", D{{"machineid", m.doc.Id}}}},
440 }, { 439 }, {
441 C: u.st.machines.Name, 440 C: u.st.machines.Name,
442 Id: m.doc.Id, 441 Id: m.doc.Id,
443 Assert: massert, 442 Assert: massert,
444 Update: D{{"$addToSet", D{{"principals", u.doc.Name}}}}, 443 Update: D{{"$addToSet", D{{"principals", u.doc.Name}}}},
445 }} 444 }}
446 » if err := u.st.runner.Run(ops, "", nil); err != nil { 445 » err = u.st.runner.Run(ops, "", nil)
niemeyer 2012/09/20 17:15:37 if err == nil || err != txn.ErrAborted { retur
rog 2012/09/21 08:35:19 Done.
447 » » if err != txn.ErrAborted { 446 » if err == nil {
448 » » » return err 447 » » u.doc.MachineId = &m.doc.Id
449 » » } 448 » » return nil
450 » » u0, err := u.st.Unit(u.Name()) 449 » }
451 » » if err != nil { 450 » if err != txn.ErrAborted {
452 » » » return err 451 » » return err
453 » » } 452 » }
454 » » m0, err := u.st.Machine(m.Id()) 453 » u0, err := u.st.Unit(u.Name())
455 » » if err != nil { 454 » if err != nil {
456 » » » return err 455 » » return err
457 » » } 456 » }
458 » » switch { 457 » m0, err := u.st.Machine(m.Id())
459 » » case u0.Life() != Alive: 458 » if err != nil {
460 » » » return unitDeadErr 459 » » return err
461 » » case m0.Life() != Alive: 460 » }
462 » » » return machineDeadErr 461 » switch {
463 » » case u0.doc.MachineId != nil: 462 » case u0.Life() != Alive:
niemeyer 2012/09/20 17:15:37 || !unused Otherwise below will yield "no unused
rog 2012/09/21 08:35:19 good catch.
464 » » » return alreadyAssignedErr 463 » » return unitDeadErr
465 » » } 464 » case m0.Life() != Alive:
466 » » return notUnusedErr 465 » » return machineDeadErr
467 » } 466 » case u0.doc.MachineId != nil || !unused:
468 » u.doc.MachineId = &m.doc.Id 467 » » return alreadyAssignedErr
469 » return nil 468 » }
469 » return inUseErr
470 } 470 }
471 471
472 // AssignToMachine assigns this unit to a given machine. 472 // AssignToMachine assigns this unit to a given machine.
473 func (u *Unit) AssignToMachine(m *Machine) error { 473 func (u *Unit) AssignToMachine(m *Machine) error {
474 err := u.assignToMachine(m, false) 474 err := u.assignToMachine(m, false)
475 if err != nil { 475 if err != nil {
476 return fmt.Errorf("cannot assign unit %q to machine %v: %v", u, m, err) 476 return fmt.Errorf("cannot assign unit %q to machine %v: %v", u, m, err)
477 } 477 }
478 return nil 478 return nil
479 } 479 }
480 480
481 var noUnusedMachines = errors.New("all machines in use") 481 var noUnusedMachines = errors.New("all machines in use")
niemeyer 2012/09/20 17:15:37 This doesn't have to be a variable. Just inline it
rog 2012/09/21 08:35:19 it's used by the next branch.
482 482
483 // AssignToUnusedMachine assigns u to a machine without other units. 483 // AssignToUnusedMachine assigns u to a machine without other units.
484 // If there are no unused machines besides machine 0, an error is returned. 484 // If there are no unused machines besides machine 0, an error is returned.
485 func (u *Unit) AssignToUnusedMachine() (m *Machine, err error) { 485 func (u *Unit) AssignToUnusedMachine() (m *Machine, err error) {
486 // Select all machines with no principals except the bootstrap machine. 486 // Select all machines with no principals except the bootstrap machine.
487 sel := D{{"principals", D{{"$size", 0}}}, {"_id", D{{"$ne", 0}}}} 487 sel := D{{"principals", D{{"$size", 0}}}, {"_id", D{{"$ne", 0}}}}
488 // TODO use Batch(1). See https://bugs.launchpad.net/mgo/+bug/1053509 488 // TODO use Batch(1). See https://bugs.launchpad.net/mgo/+bug/1053509
489 iter := u.st.machines.Find(sel).Batch(2).Prefetch(0).Iter() 489 iter := u.st.machines.Find(sel).Batch(2).Prefetch(0).Iter()
490 var mdoc machineDoc 490 var mdoc machineDoc
491 for iter.Next(&mdoc) { 491 for iter.Next(&mdoc) {
492 m := newMachine(u.st, &mdoc) 492 m := newMachine(u.st, &mdoc)
493 493
494 » » switch err := u.assignToMachine(m, true); err { 494 » » err := u.assignToMachine(m, true)
niemeyer 2012/09/20 17:15:37 This switch seems to be making the logic less read
rog 2012/09/21 08:35:19 Done.
495 » » case nil: 495 » » if err == nil {
496 return m, nil 496 return m, nil
497 » » case notUnusedErr, machineDeadErr: 497 » » }
498 » » default: 498 » » if err != inUseErr && err != machineDeadErr {
499 » » » return nil, fmt.Errorf("cannot assign unit %q to unused machine: %v", u.Name(), err) 499 » » » return nil, fmt.Errorf("cannot assign unit %q to unused machine: %v", u, err)
niemeyer 2012/09/20 17:15:37 s/u.Name()/u/
rog 2012/09/21 08:35:19 Done.
500 » » } 500 » » }
501 » } 501 » }
502 » // TODO check to see if the unit has now been assigned,
niemeyer 2012/09/20 17:15:37 I'd not fix this and drop the TODO. We can keep lo
rog 2012/09/21 08:35:19 Done.
503 » // and if so return a more descriptive error.
504 return nil, noUnusedMachines 502 return nil, noUnusedMachines
505 } 503 }
506 504
507 // UnassignFromMachine removes the assignment between this unit and the 505 // UnassignFromMachine removes the assignment between this unit and the
508 // machine it's assigned to. 506 // machine it's assigned to.
509 func (u *Unit) UnassignFromMachine() (err error) { 507 func (u *Unit) UnassignFromMachine() (err error) {
510 // TODO check local machine id and add an assert that the 508 // TODO check local machine id and add an assert that the
511 // machine id is as expected. 509 // machine id is as expected.
512 ops := []txn.Op{{ 510 ops := []txn.Op{{
513 C: u.st.units.Name, 511 C: u.st.units.Name,
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 return p1.Protocol < p2.Protocol 632 return p1.Protocol < p2.Protocol
635 } 633 }
636 return p1.Number < p2.Number 634 return p1.Number < p2.Number
637 } 635 }
638 636
639 // SortPorts sorts the given ports, first by protocol, 637 // SortPorts sorts the given ports, first by protocol,
640 // then by number. 638 // then by number.
641 func SortPorts(ports []Port) { 639 func SortPorts(ports []Port) {
642 sort.Sort(portSlice(ports)) 640 sort.Sort(portSlice(ports))
643 } 641 }
LEFTRIGHT

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