LEFT | RIGHT |
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 state | 4 package state |
5 | 5 |
6 import ( | 6 import ( |
7 "fmt" | 7 "fmt" |
8 "strconv" | 8 "strconv" |
9 | 9 |
| 10 "labix.org/v2/mgo/bson" |
10 "labix.org/v2/mgo/txn" | 11 "labix.org/v2/mgo/txn" |
11 | 12 |
12 "launchpad.net/juju-core/constraints" | 13 "launchpad.net/juju-core/constraints" |
13 "launchpad.net/juju-core/errors" | 14 "launchpad.net/juju-core/errors" |
14 "launchpad.net/juju-core/instance" | 15 "launchpad.net/juju-core/instance" |
15 "launchpad.net/juju-core/replicaset" | 16 "launchpad.net/juju-core/replicaset" |
16 "launchpad.net/juju-core/state/api/params" | 17 "launchpad.net/juju-core/state/api/params" |
17 "launchpad.net/juju-core/utils" | 18 "launchpad.net/juju-core/utils" |
18 ) | 19 ) |
19 | 20 |
(...skipping 24 matching lines...) Expand all Loading... |
44 | 45 |
45 // InstanceId holds the instance id to associate with the machine. | 46 // InstanceId holds the instance id to associate with the machine. |
46 // If this is empty, the provisioner will try to provision the machine. | 47 // If this is empty, the provisioner will try to provision the machine. |
47 // If this is non-empty, the HardwareCharacteristics and Nonce | 48 // If this is non-empty, the HardwareCharacteristics and Nonce |
48 // fields must be set appropriately. | 49 // fields must be set appropriately. |
49 InstanceId instance.Id | 50 InstanceId instance.Id |
50 | 51 |
51 // HardwareCharacteristics holds the h/w characteristics to | 52 // HardwareCharacteristics holds the h/w characteristics to |
52 // be associated with the machine. | 53 // be associated with the machine. |
53 HardwareCharacteristics instance.HardwareCharacteristics | 54 HardwareCharacteristics instance.HardwareCharacteristics |
| 55 |
| 56 // IncludeNetworks holds a list of networks the machine should be |
| 57 // part of. |
| 58 IncludeNetworks []string |
| 59 |
| 60 // ExcludeNetworks holds a list of network the machine should not |
| 61 // be part of. |
| 62 ExcludeNetworks []string |
54 | 63 |
55 // Nonce holds a unique value that can be used to check | 64 // Nonce holds a unique value that can be used to check |
56 // if a new instance was really started for this machine. | 65 // if a new instance was really started for this machine. |
57 // See Machine.SetProvisioned. This must be set if InstanceId is set. | 66 // See Machine.SetProvisioned. This must be set if InstanceId is set. |
58 Nonce string | 67 Nonce string |
59 | 68 |
60 // Dirty signifies whether the new machine will be treated | 69 // Dirty signifies whether the new machine will be treated |
61 // as unclean for unit-assignment purposes. | 70 // as unclean for unit-assignment purposes. |
62 Dirty bool | 71 Dirty bool |
63 | 72 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 if err := st.precheckInstance(template.Series, template.Constrai
nts); err != nil { | 238 if err := st.precheckInstance(template.Series, template.Constrai
nts); err != nil { |
230 return nil, nil, err | 239 return nil, nil, err |
231 } | 240 } |
232 } | 241 } |
233 seq, err := st.sequence("machine") | 242 seq, err := st.sequence("machine") |
234 if err != nil { | 243 if err != nil { |
235 return nil, nil, err | 244 return nil, nil, err |
236 } | 245 } |
237 mdoc := machineDocForTemplate(template, strconv.Itoa(seq)) | 246 mdoc := machineDocForTemplate(template, strconv.Itoa(seq)) |
238 var ops []txn.Op | 247 var ops []txn.Op |
239 » ops = append(ops, st.insertNewMachineOps(mdoc, template.Constraints)...) | 248 » ops = append(ops, st.insertNewMachineOps(mdoc, template)...) |
240 ops = append(ops, st.insertNewContainerRefOp(mdoc.Id)) | 249 ops = append(ops, st.insertNewContainerRefOp(mdoc.Id)) |
241 if template.InstanceId != "" { | 250 if template.InstanceId != "" { |
242 ops = append(ops, txn.Op{ | 251 ops = append(ops, txn.Op{ |
243 C: st.instanceData.Name, | 252 C: st.instanceData.Name, |
244 Id: mdoc.Id, | 253 Id: mdoc.Id, |
245 Assert: txn.DocMissing, | 254 Assert: txn.DocMissing, |
246 Insert: &instanceData{ | 255 Insert: &instanceData{ |
247 Id: mdoc.Id, | 256 Id: mdoc.Id, |
248 InstanceId: template.InstanceId, | 257 InstanceId: template.InstanceId, |
249 Arch: template.HardwareCharacteristics.Arc
h, | 258 Arch: template.HardwareCharacteristics.Arc
h, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 if !parent.supportsContainerType(containerType) { | 313 if !parent.supportsContainerType(containerType) { |
305 return nil, nil, fmt.Errorf("machine %s cannot host %s container
s", parentId, containerType) | 314 return nil, nil, fmt.Errorf("machine %s cannot host %s container
s", parentId, containerType) |
306 } | 315 } |
307 newId, err := st.newContainerId(parentId, containerType) | 316 newId, err := st.newContainerId(parentId, containerType) |
308 if err != nil { | 317 if err != nil { |
309 return nil, nil, err | 318 return nil, nil, err |
310 } | 319 } |
311 mdoc := machineDocForTemplate(template, newId) | 320 mdoc := machineDocForTemplate(template, newId) |
312 mdoc.ContainerType = string(containerType) | 321 mdoc.ContainerType = string(containerType) |
313 var ops []txn.Op | 322 var ops []txn.Op |
314 » ops = append(ops, st.insertNewMachineOps(mdoc, template.Constraints)...) | 323 » ops = append(ops, st.insertNewMachineOps(mdoc, template)...) |
315 ops = append(ops, | 324 ops = append(ops, |
316 // Update containers record for host machine. | 325 // Update containers record for host machine. |
317 st.addChildToContainerRefOp(parentId, mdoc.Id), | 326 st.addChildToContainerRefOp(parentId, mdoc.Id), |
318 // Create a containers reference document for the container itse
lf. | 327 // Create a containers reference document for the container itse
lf. |
319 st.insertNewContainerRefOp(mdoc.Id), | 328 st.insertNewContainerRefOp(mdoc.Id), |
320 ) | 329 ) |
321 return mdoc, ops, nil | 330 return mdoc, ops, nil |
322 } | 331 } |
323 | 332 |
324 // newContainerId returns a new id for a machine within the machine | 333 // newContainerId returns a new id for a machine within the machine |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 if err != nil { | 374 if err != nil { |
366 return nil, nil, err | 375 return nil, nil, err |
367 } | 376 } |
368 template, err = st.effectiveMachineTemplate(template, false) | 377 template, err = st.effectiveMachineTemplate(template, false) |
369 if err != nil { | 378 if err != nil { |
370 return nil, nil, err | 379 return nil, nil, err |
371 } | 380 } |
372 mdoc := machineDocForTemplate(template, newId) | 381 mdoc := machineDocForTemplate(template, newId) |
373 mdoc.ContainerType = string(containerType) | 382 mdoc.ContainerType = string(containerType) |
374 var ops []txn.Op | 383 var ops []txn.Op |
375 » ops = append(ops, st.insertNewMachineOps(parentDoc, parentTemplate.Const
raints)...) | 384 » ops = append(ops, st.insertNewMachineOps(parentDoc, parentTemplate)...) |
376 » ops = append(ops, st.insertNewMachineOps(mdoc, template.Constraints)...) | 385 » ops = append(ops, st.insertNewMachineOps(mdoc, template)...) |
377 ops = append(ops, | 386 ops = append(ops, |
378 // The host machine doesn't exist yet, create a new containers r
ecord. | 387 // The host machine doesn't exist yet, create a new containers r
ecord. |
379 st.insertNewContainerRefOp(mdoc.Id), | 388 st.insertNewContainerRefOp(mdoc.Id), |
380 // Create a containers reference document for the container itse
lf. | 389 // Create a containers reference document for the container itse
lf. |
381 st.insertNewContainerRefOp(parentDoc.Id, mdoc.Id), | 390 st.insertNewContainerRefOp(parentDoc.Id, mdoc.Id), |
382 ) | 391 ) |
383 return mdoc, ops, nil | 392 return mdoc, ops, nil |
384 } | 393 } |
385 | 394 |
386 func machineDocForTemplate(template MachineTemplate, id string) *machineDoc { | 395 func machineDocForTemplate(template MachineTemplate, id string) *machineDoc { |
387 return &machineDoc{ | 396 return &machineDoc{ |
388 Id: id, | 397 Id: id, |
389 Series: template.Series, | 398 Series: template.Series, |
390 Jobs: template.Jobs, | 399 Jobs: template.Jobs, |
391 Clean: !template.Dirty, | 400 Clean: !template.Dirty, |
392 Principals: template.principals, | 401 Principals: template.principals, |
393 Life: Alive, | 402 Life: Alive, |
394 InstanceId: template.InstanceId, | 403 InstanceId: template.InstanceId, |
395 Nonce: template.Nonce, | 404 Nonce: template.Nonce, |
396 Addresses: instanceAddressesToAddresses(template.Addresses), | 405 Addresses: instanceAddressesToAddresses(template.Addresses), |
397 NoVote: template.NoVote, | 406 NoVote: template.NoVote, |
398 } | 407 } |
399 } | 408 } |
400 | 409 |
401 // insertNewMachineOps returns operations to insert the given machine | 410 // insertNewMachineOps returns operations to insert the given machine |
402 // document and its associated constraints into the database. | 411 // document into the database, based on the given template. Only the |
403 func (st *State) insertNewMachineOps(mdoc *machineDoc, cons constraints.Value) [
]txn.Op { | 412 // constraints and networks are used from the template. |
| 413 func (st *State) insertNewMachineOps(mdoc *machineDoc, template MachineTemplate)
[]txn.Op { |
404 return []txn.Op{ | 414 return []txn.Op{ |
405 { | 415 { |
406 C: st.machines.Name, | 416 C: st.machines.Name, |
407 Id: mdoc.Id, | 417 Id: mdoc.Id, |
408 Assert: txn.DocMissing, | 418 Assert: txn.DocMissing, |
409 Insert: mdoc, | 419 Insert: mdoc, |
410 }, | 420 }, |
411 » » createConstraintsOp(st, machineGlobalKey(mdoc.Id), cons), | 421 » » createConstraintsOp(st, machineGlobalKey(mdoc.Id), template.Cons
traints), |
412 createStatusOp(st, machineGlobalKey(mdoc.Id), statusDoc{ | 422 createStatusOp(st, machineGlobalKey(mdoc.Id), statusDoc{ |
413 Status: params.StatusPending, | 423 Status: params.StatusPending, |
414 }), | 424 }), |
| 425 createNetworksOp(st, machineGlobalKey(mdoc.Id), |
| 426 template.IncludeNetworks, |
| 427 template.ExcludeNetworks, |
| 428 ), |
415 } | 429 } |
416 } | 430 } |
417 | 431 |
418 func hasJob(jobs []MachineJob, job MachineJob) bool { | 432 func hasJob(jobs []MachineJob, job MachineJob) bool { |
419 for _, j := range jobs { | 433 for _, j := range jobs { |
420 if j == job { | 434 if j == job { |
421 return true | 435 return true |
422 } | 436 } |
423 } | 437 } |
424 return false | 438 return false |
(...skipping 30 matching lines...) Expand all Loading... |
455 if err != nil { | 469 if err != nil { |
456 return nil, fmt.Errorf("cannot get state server info: %v
", err) | 470 return nil, fmt.Errorf("cannot get state server info: %v
", err) |
457 } | 471 } |
458 if len(currentInfo.MachineIds) > 0 || len(currentInfo.VotingMach
ineIds) > 0 { | 472 if len(currentInfo.MachineIds) > 0 || len(currentInfo.VotingMach
ineIds) > 0 { |
459 return nil, fmt.Errorf("state servers already exist") | 473 return nil, fmt.Errorf("state servers already exist") |
460 } | 474 } |
461 } | 475 } |
462 ops := []txn.Op{{ | 476 ops := []txn.Op{{ |
463 C: st.stateServers.Name, | 477 C: st.stateServers.Name, |
464 Id: environGlobalKey, | 478 Id: environGlobalKey, |
465 » » Assert: D{{ | 479 » » Assert: bson.D{{ |
466 » » » "$and", []D{ | 480 » » » "$and", []bson.D{ |
467 » » » » {{"machineids", D{{"$size", len(currentInfo.Mach
ineIds)}}}}, | 481 » » » » {{"machineids", bson.D{{"$size", len(currentInfo
.MachineIds)}}}}, |
468 » » » » {{"votingmachineids", D{{"$size", len(currentInf
o.VotingMachineIds)}}}}, | 482 » » » » {{"votingmachineids", bson.D{{"$size", len(curre
ntInfo.VotingMachineIds)}}}}, |
469 }, | 483 }, |
470 }}, | 484 }}, |
471 » » Update: D{ | 485 » » Update: bson.D{ |
472 » » » {"$addToSet", D{{"machineids", D{{"$each", newIds}}}}}, | 486 » » » {"$addToSet", bson.D{{"machineids", bson.D{{"$each", new
Ids}}}}}, |
473 » » » {"$addToSet", D{{"votingmachineids", D{{"$each", newVoti
ngIds}}}}}, | 487 » » » {"$addToSet", bson.D{{"votingmachineids", bson.D{{"$each
", newVotingIds}}}}}, |
474 }, | 488 }, |
475 }} | 489 }} |
476 return ops, nil | 490 return ops, nil |
477 } | 491 } |
478 | 492 |
479 // EnsureAvailability adds state server machines as necessary to make | 493 // EnsureAvailability adds state server machines as necessary to make |
480 // the number of live state servers equal to numStateServers. The given | 494 // the number of live state servers equal to numStateServers. The given |
481 // constraints and series will be attached to any new machines. | 495 // constraints and series will be attached to any new machines. |
482 // | 496 // |
483 // TODO(rog): | 497 // TODO(rog): |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 if err != nil { | 544 if err != nil { |
531 return fmt.Errorf("cannot prepare machine add operations: %v", e
rr) | 545 return fmt.Errorf("cannot prepare machine add operations: %v", e
rr) |
532 } | 546 } |
533 ops = append(ops, ssOps...) | 547 ops = append(ops, ssOps...) |
534 err = st.runTransaction(ops) | 548 err = st.runTransaction(ops) |
535 if err != nil { | 549 if err != nil { |
536 return fmt.Errorf("failed to create new state server machines: %
v", err) | 550 return fmt.Errorf("failed to create new state server machines: %
v", err) |
537 } | 551 } |
538 return nil | 552 return nil |
539 } | 553 } |
LEFT | RIGHT |