Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 package state | 1 package state |
2 | 2 |
3 import ( | 3 import ( |
4 "errors" | 4 "errors" |
5 "fmt" | 5 "fmt" |
6 "launchpad.net/goyaml" | 6 "launchpad.net/goyaml" |
7 "launchpad.net/gozk/zookeeper" | 7 "launchpad.net/gozk/zookeeper" |
8 "sort" | 8 "sort" |
9 ) | 9 ) |
10 | 10 |
11 // The protocol version, which is stored in the /topology node under | 11 // The protocol version, which is stored in the /topology node under |
12 // the "version" key. The protocol version should *only* be updated | 12 // the "version" key. The protocol version should *only* be updated |
13 // when we know that a version is in fact actually incompatible. | 13 // when we know that a version is in fact actually incompatible. |
14 | |
15 const topologyVersion = 1 | 14 const topologyVersion = 1 |
16 | 15 |
17 // zkTopology is used to marshal and unmarshal the content | 16 // zkTopology is used to marshal and unmarshal the content |
18 // of the /topology node in ZooKeeper. | 17 // of the /topology node in ZooKeeper. |
19 type zkTopology struct { | 18 type zkTopology struct { |
20 Version int | 19 Version int |
21 Machines map[string]*zkMachine | 20 Machines map[string]*zkMachine |
22 Services map[string]*zkService | 21 Services map[string]*zkService |
23 UnitSequence map[string]int "unit-sequence" | 22 UnitSequence map[string]int "unit-sequence" |
24 Relations map[string]*zkRelation | 23 Relations map[string]*zkRelation |
(...skipping 12 matching lines...) Expand all Loading... | |
37 } | 36 } |
38 | 37 |
39 // zkUnit represents the unit data within the /topology | 38 // zkUnit represents the unit data within the /topology |
40 // node in ZooKeeper. | 39 // node in ZooKeeper. |
41 type zkUnit struct { | 40 type zkUnit struct { |
42 Sequence int | 41 Sequence int |
43 Machine string | 42 Machine string |
44 } | 43 } |
45 | 44 |
46 // zkRelation represents the relation data within the· | 45 // zkRelation represents the relation data within the· |
47 // /topology node in ZooKeeper. "Services" references to | 46 // /topology node in ZooKeeper. |
48 // the service keys of provider, consumer or peer. | |
49 type zkRelation struct { | 47 type zkRelation struct { |
50 Key string "omitempty" | |
51 Interface string | 48 Interface string |
52 Scope RelationScope | 49 Scope RelationScope |
53 Services map[RelationRole]string | 50 Services map[RelationRole]string |
54 } | 51 } |
55 | 52 |
56 // check validates if interface isn't empty and the· | 53 // check verifies that r is a proper relation. |
57 // services are provider and consumer or peer. | |
58 func (r *zkRelation) check() error { | 54 func (r *zkRelation) check() error { |
59 if len(r.Interface) == 0 { | 55 if len(r.Interface) == 0 { |
60 return fmt.Errorf("relation interface is empty") | 56 return fmt.Errorf("relation interface is empty") |
61 } | 57 } |
62 » switch len(r.Services) { | 58 » if len(r.Services) == 0 { |
63 » case 0: | 59 » » return fmt.Errorf("relation has no services") |
64 » » return fmt.Errorf("no service defined") | 60 » } |
65 » case 1: | 61 » counterpart := map[RelationRole]RelationRole{ |
66 » » if r.Services[RolePeer] == "" { | 62 » » RoleRequirer: RoleProvider, |
67 » » » return fmt.Errorf("provider or consumer service missing" ) | 63 » » RoleProvider: RoleRequirer, |
68 » » } | 64 » » RolePeer: RolePeer, |
69 » case 2: | 65 » } |
70 » » if r.Services[RoleProvider] == "" || r.Services[RoleConsumer] == "" { | 66 » for serviceRole, serviceKey := range r.Services { |
71 » » » return fmt.Errorf("mixed peer with provider or consumer service") | 67 » » if serviceKey == "" { |
72 » » } | 68 » » » return fmt.Errorf("relation has %s service with empty ke y", serviceRole) |
73 » default: | 69 » » } |
74 » » return fmt.Errorf("too much services defined") | 70 » » counterRole, ok := counterpart[serviceRole] |
fwereade
2012/05/23 10:28:02
s/much/many/
TheMue
2012/05/23 10:43:04
Done.
| |
71 » » if !ok { | |
72 » » » return fmt.Errorf("relation has unknown service role: %q ", serviceRole) | |
73 » » } | |
74 » » if _, ok := r.Services[counterRole]; !ok { | |
75 » » » return fmt.Errorf("relation has %s but no %s", serviceRo le, counterRole) | |
76 » » } | |
77 » } | |
78 » if len(r.Services) > 2 { | |
79 » » return fmt.Errorf("relation with mixed peer, provider, and requi rer roles") | |
75 } | 80 } |
76 return nil | 81 return nil |
77 } | 82 } |
78 | 83 |
79 // topology is an internal helper that handles the content | 84 // topology is an internal helper that handles the content |
80 // of the /topology node in ZooKeeper. | 85 // of the /topology node in ZooKeeper. |
81 type topology struct { | 86 type topology struct { |
82 topology *zkTopology | 87 topology *zkTopology |
83 } | 88 } |
84 | 89 |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 return err | 363 return err |
359 } | 364 } |
360 unit := t.topology.Services[serviceKey].Units[unitKey] | 365 unit := t.topology.Services[serviceKey].Units[unitKey] |
361 if unit.Machine == "" { | 366 if unit.Machine == "" { |
362 return fmt.Errorf("unit %q in service %q not assigned to a machi ne", unitKey, serviceKey) | 367 return fmt.Errorf("unit %q in service %q not assigned to a machi ne", unitKey, serviceKey) |
363 } | 368 } |
364 unit.Machine = "" | 369 unit.Machine = "" |
365 return nil | 370 return nil |
366 } | 371 } |
367 | 372 |
368 // Relation returns a relation with the given key or an error if it doesn't exis t. | 373 // Relation returns the relation with key from the topology. |
369 func (t *topology) Relation(relationKey string) (*zkRelation, error) { | 374 func (t *topology) Relation(key string) (*zkRelation, error) { |
370 » if t.topology.Relations == nil || t.topology.Relations[relationKey] == n il { | 375 » if t.topology.Relations == nil || t.topology.Relations[key] == nil { |
371 » » return nil, fmt.Errorf("relation %q does not exist", relationKey ) | 376 » » return nil, fmt.Errorf("relation %q does not exist", key) |
372 » } | 377 » } |
373 » return t.topology.Relations[relationKey], nil | 378 » return t.topology.Relations[key], nil |
374 } | 379 } |
375 | 380 |
376 // AddRelation adds a new relation with the given key and relation data. | 381 // AddRelation adds a new relation with the given key and relation data. |
377 func (t *topology) AddRelation(relationKey string, relation *zkRelation) error { | 382 func (t *topology) AddRelation(relationKey string, relation *zkRelation) error { |
378 if t.topology.Relations == nil { | 383 if t.topology.Relations == nil { |
379 t.topology.Relations = make(map[string]*zkRelation) | 384 t.topology.Relations = make(map[string]*zkRelation) |
380 } | 385 } |
381 » _, err := t.Relation(relationKey) | 386 » _, ok := t.topology.Relations[relationKey] |
382 » if err == nil { | 387 » if ok { |
383 » » // No error means relation with key already exists. | |
384 return fmt.Errorf("relation key %q already in use", relationKey) | 388 return fmt.Errorf("relation key %q already in use", relationKey) |
385 } | 389 } |
386 // Check if the relation definition and the service keys are valid. | 390 // Check if the relation definition and the service keys are valid. |
387 » err = relation.check() | 391 » if err := relation.check(); err != nil { |
388 » if err != nil { | |
389 return err | 392 return err |
390 } | 393 } |
391 for _, serviceKey := range relation.Services { | 394 for _, serviceKey := range relation.Services { |
392 » » if err = t.assertService(serviceKey); err != nil { | 395 » » if err := t.assertService(serviceKey); err != nil { |
393 return err | 396 return err |
394 } | 397 } |
395 } | 398 } |
396 if relation.Services[RolePeer] == "" { | 399 if relation.Services[RolePeer] == "" { |
397 providerKey := relation.Services[RoleProvider] | 400 providerKey := relation.Services[RoleProvider] |
398 » » consumerKey := relation.Services[RoleConsumer] | 401 » » consumerKey := relation.Services[RoleRequirer] |
399 if providerKey == consumerKey { | 402 if providerKey == consumerKey { |
400 return fmt.Errorf("provider and consumer keys must not b e the same") | 403 return fmt.Errorf("provider and consumer keys must not b e the same") |
401 } | 404 } |
402 } | 405 } |
403 relation.Key = relationKey | |
404 t.topology.Relations[relationKey] = relation | 406 t.topology.Relations[relationKey] = relation |
405 return nil | 407 return nil |
406 } | 408 } |
407 | 409 |
408 // RelationKeys returns all relation keys. | 410 // RelationKeys returns the keys for all relations in the topology. |
409 func (t *topology) RelationKeys() []string { | 411 func (t *topology) RelationKeys() []string { |
410 keys := []string{} | 412 keys := []string{} |
411 for key, _ := range t.topology.Relations { | 413 for key, _ := range t.topology.Relations { |
412 keys = append(keys, key) | 414 keys = append(keys, key) |
413 } | 415 } |
414 sort.Strings(keys) | 416 sort.Strings(keys) |
415 return keys | 417 return keys |
416 } | 418 } |
417 | 419 |
418 // RemoveRelation removes a relation. | 420 // RemoveRelation removes the relation with key from the topology. |
419 func (t *topology) RemoveRelation(key string) { | 421 func (t *topology) RemoveRelation(key string) { |
420 delete(t.topology.Relations, key) | 422 delete(t.topology.Relations, key) |
421 } | 423 } |
422 | 424 |
423 // RelationWithService returns the relation data for a given | 425 // RelationsForService returns all relations that the service |
424 // relation key if the service with the given key is assigned | 426 // with serviceKey is part of. |
425 // to the relation. | 427 func (t *topology) RelationsForService(serviceKey string) (map[string]*zkRelatio n, error) { |
426 func (t *topology) RelationWithService(relationKey, serviceKey string) (*zkRelat ion, error) { | |
427 if err := t.assertService(serviceKey); err != nil { | 428 if err := t.assertService(serviceKey); err != nil { |
428 return nil, err | 429 return nil, err |
429 } | 430 } |
430 » if err := t.assertRelation(relationKey); err != nil { | 431 » relations := make(map[string]*zkRelation) |
431 » » return nil, err | 432 » for relationKey, relation := range t.topology.Relations { |
432 » } | 433 » » for _, roleServiceKey := range relation.Services { |
433 » relation := t.topology.Relations[relationKey] | 434 » » » if roleServiceKey == serviceKey { |
434 » for _, key := range relation.Services { | 435 » » » » relations[relationKey] = relation |
435 » » if key == serviceKey { | 436 » » » » break |
436 » » » return relation, nil | |
437 » » } | |
438 » } | |
439 » return nil, fmt.Errorf("service %q is not assigned to relation %q", serv iceKey, relationKey) | |
440 } | |
441 | |
442 // RelationsForService returns all relations for a | |
443 // given service key. | |
444 func (t *topology) RelationsForService(serviceKey string) ([]*zkRelation, error) { | |
445 » if err := t.assertService(serviceKey); err != nil { | |
446 » » return nil, err | |
447 » } | |
448 » relations := []*zkRelation{} | |
449 » for _, relation := range t.topology.Relations { | |
450 » » for _, key := range relation.Services { | |
451 » » » if key == serviceKey { | |
452 » » » » relations = append(relations, relation) | |
453 } | 437 } |
454 } | 438 } |
455 } | 439 } |
456 return relations, nil | 440 return relations, nil |
457 } | 441 } |
458 | 442 |
459 // assertMachine checks if a machine exists. | 443 // assertMachine checks if a machine exists. |
460 func (t *topology) assertMachine(machineKey string) error { | 444 func (t *topology) assertMachine(machineKey string) error { |
461 if _, ok := t.topology.Machines[machineKey]; !ok { | 445 if _, ok := t.topology.Machines[machineKey]; !ok { |
462 return fmt.Errorf("machine with key %q not found", machineKey) | 446 return fmt.Errorf("machine with key %q not found", machineKey) |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
521 } | 505 } |
522 } | 506 } |
523 // Apply the passed function. | 507 // Apply the passed function. |
524 if err = f(it); err != nil { | 508 if err = f(it); err != nil { |
525 return "", err | 509 return "", err |
526 } | 510 } |
527 return it.dump() | 511 return it.dump() |
528 } | 512 } |
529 return zk.RetryChange(zkTopologyPath, 0, zkPermAll, change) | 513 return zk.RetryChange(zkTopologyPath, 0, zkPermAll, change) |
530 } | 514 } |
LEFT | RIGHT |