nodes.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package store
  2. import (
  3. "strconv"
  4. "strings"
  5. "github.com/docker/swarmkit/api"
  6. memdb "github.com/hashicorp/go-memdb"
  7. )
  8. const tableNode = "node"
  9. func init() {
  10. register(ObjectStoreConfig{
  11. Table: &memdb.TableSchema{
  12. Name: tableNode,
  13. Indexes: map[string]*memdb.IndexSchema{
  14. indexID: {
  15. Name: indexID,
  16. Unique: true,
  17. Indexer: api.NodeIndexerByID{},
  18. },
  19. // TODO(aluzzardi): Use `indexHostname` instead.
  20. indexName: {
  21. Name: indexName,
  22. AllowMissing: true,
  23. Indexer: nodeIndexerByHostname{},
  24. },
  25. indexRole: {
  26. Name: indexRole,
  27. Indexer: nodeIndexerByRole{},
  28. },
  29. indexMembership: {
  30. Name: indexMembership,
  31. Indexer: nodeIndexerByMembership{},
  32. },
  33. indexCustom: {
  34. Name: indexCustom,
  35. Indexer: api.NodeCustomIndexer{},
  36. AllowMissing: true,
  37. },
  38. },
  39. },
  40. Save: func(tx ReadTx, snapshot *api.StoreSnapshot) error {
  41. var err error
  42. snapshot.Nodes, err = FindNodes(tx, All)
  43. return err
  44. },
  45. Restore: func(tx Tx, snapshot *api.StoreSnapshot) error {
  46. nodes, err := FindNodes(tx, All)
  47. if err != nil {
  48. return err
  49. }
  50. for _, n := range nodes {
  51. if err := DeleteNode(tx, n.ID); err != nil {
  52. return err
  53. }
  54. }
  55. for _, n := range snapshot.Nodes {
  56. if err := CreateNode(tx, n); err != nil {
  57. return err
  58. }
  59. }
  60. return nil
  61. },
  62. ApplyStoreAction: func(tx Tx, sa api.StoreAction) error {
  63. switch v := sa.Target.(type) {
  64. case *api.StoreAction_Node:
  65. obj := v.Node
  66. switch sa.Action {
  67. case api.StoreActionKindCreate:
  68. return CreateNode(tx, obj)
  69. case api.StoreActionKindUpdate:
  70. return UpdateNode(tx, obj)
  71. case api.StoreActionKindRemove:
  72. return DeleteNode(tx, obj.ID)
  73. }
  74. }
  75. return errUnknownStoreAction
  76. },
  77. })
  78. }
  79. // CreateNode adds a new node to the store.
  80. // Returns ErrExist if the ID is already taken.
  81. func CreateNode(tx Tx, n *api.Node) error {
  82. return tx.create(tableNode, n)
  83. }
  84. // UpdateNode updates an existing node in the store.
  85. // Returns ErrNotExist if the node doesn't exist.
  86. func UpdateNode(tx Tx, n *api.Node) error {
  87. return tx.update(tableNode, n)
  88. }
  89. // DeleteNode removes a node from the store.
  90. // Returns ErrNotExist if the node doesn't exist.
  91. func DeleteNode(tx Tx, id string) error {
  92. return tx.delete(tableNode, id)
  93. }
  94. // GetNode looks up a node by ID.
  95. // Returns nil if the node doesn't exist.
  96. func GetNode(tx ReadTx, id string) *api.Node {
  97. n := tx.get(tableNode, id)
  98. if n == nil {
  99. return nil
  100. }
  101. return n.(*api.Node)
  102. }
  103. // FindNodes selects a set of nodes and returns them.
  104. func FindNodes(tx ReadTx, by By) ([]*api.Node, error) {
  105. checkType := func(by By) error {
  106. switch by.(type) {
  107. case byName, byNamePrefix, byIDPrefix, byRole, byMembership, byCustom, byCustomPrefix:
  108. return nil
  109. default:
  110. return ErrInvalidFindBy
  111. }
  112. }
  113. nodeList := []*api.Node{}
  114. appendResult := func(o api.StoreObject) {
  115. nodeList = append(nodeList, o.(*api.Node))
  116. }
  117. err := tx.find(tableNode, by, checkType, appendResult)
  118. return nodeList, err
  119. }
  120. type nodeIndexerByHostname struct{}
  121. func (ni nodeIndexerByHostname) FromArgs(args ...interface{}) ([]byte, error) {
  122. return fromArgs(args...)
  123. }
  124. func (ni nodeIndexerByHostname) FromObject(obj interface{}) (bool, []byte, error) {
  125. n := obj.(*api.Node)
  126. if n.Description == nil {
  127. return false, nil, nil
  128. }
  129. // Add the null character as a terminator
  130. return true, []byte(strings.ToLower(n.Description.Hostname) + "\x00"), nil
  131. }
  132. func (ni nodeIndexerByHostname) PrefixFromArgs(args ...interface{}) ([]byte, error) {
  133. return prefixFromArgs(args...)
  134. }
  135. type nodeIndexerByRole struct{}
  136. func (ni nodeIndexerByRole) FromArgs(args ...interface{}) ([]byte, error) {
  137. return fromArgs(args...)
  138. }
  139. func (ni nodeIndexerByRole) FromObject(obj interface{}) (bool, []byte, error) {
  140. n := obj.(*api.Node)
  141. // Add the null character as a terminator
  142. return true, []byte(strconv.FormatInt(int64(n.Role), 10) + "\x00"), nil
  143. }
  144. type nodeIndexerByMembership struct{}
  145. func (ni nodeIndexerByMembership) FromArgs(args ...interface{}) ([]byte, error) {
  146. return fromArgs(args...)
  147. }
  148. func (ni nodeIndexerByMembership) FromObject(obj interface{}) (bool, []byte, error) {
  149. n := obj.(*api.Node)
  150. // Add the null character as a terminator
  151. return true, []byte(strconv.FormatInt(int64(n.Spec.Membership), 10) + "\x00"), nil
  152. }