Statistics
| Branch: | Tag: | Revision:

root / doc / examples / dumb-allocator @ a2d32034

History | View | Annotate | Download (2.9 kB)

1 298fe380 Iustin Pop
#!/usr/bin/python
2 298fe380 Iustin Pop
#
3 298fe380 Iustin Pop
4 298fe380 Iustin Pop
# Copyright (C) 2008 Google Inc.
5 298fe380 Iustin Pop
#
6 298fe380 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 298fe380 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 298fe380 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 298fe380 Iustin Pop
# (at your option) any later version.
10 298fe380 Iustin Pop
#
11 298fe380 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 298fe380 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 298fe380 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 298fe380 Iustin Pop
# General Public License for more details.
15 298fe380 Iustin Pop
#
16 298fe380 Iustin Pop
# You should have received a copy of the GNU General Public License
17 298fe380 Iustin Pop
# along with this program; if not, write to the Free Software
18 298fe380 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 298fe380 Iustin Pop
# 02110-1301, USA.
20 298fe380 Iustin Pop
21 298fe380 Iustin Pop
"""Simple first-fit allocator for ganeti instance allocation framework.
22 298fe380 Iustin Pop
23 298fe380 Iustin Pop
This allocator just iterates over the nodes and selects the first one
24 298fe380 Iustin Pop
that fits in both memory and disk space, without any consideration for
25 298fe380 Iustin Pop
equal spread or VCPU oversubscription.
26 298fe380 Iustin Pop
27 298fe380 Iustin Pop
"""
28 298fe380 Iustin Pop
import simplejson
29 298fe380 Iustin Pop
import sys
30 298fe380 Iustin Pop
31 298fe380 Iustin Pop
32 298fe380 Iustin Pop
def SelectNode(nodes, request, to_skip):
33 298fe380 Iustin Pop
  """Select a node for the given instance
34 298fe380 Iustin Pop
35 298fe380 Iustin Pop
  """
36 298fe380 Iustin Pop
  disk_size = request["disk_space_total"]
37 298fe380 Iustin Pop
  selected = None
38 298fe380 Iustin Pop
  for nname, ninfo in nodes.iteritems():
39 298fe380 Iustin Pop
    if nname in to_skip:
40 298fe380 Iustin Pop
      continue
41 298fe380 Iustin Pop
    if request["memory"] > ninfo["free_memory"]:
42 298fe380 Iustin Pop
      continue
43 298fe380 Iustin Pop
    if disk_size > ninfo["free_disk"]:
44 298fe380 Iustin Pop
      continue
45 298fe380 Iustin Pop
    selected = nname
46 298fe380 Iustin Pop
    break
47 298fe380 Iustin Pop
  return selected
48 298fe380 Iustin Pop
49 298fe380 Iustin Pop
50 538475ca Iustin Pop
def OutputError(text, exit_code=1):
51 298fe380 Iustin Pop
  """Builds an error response with a given info message.
52 298fe380 Iustin Pop
53 298fe380 Iustin Pop
  """
54 298fe380 Iustin Pop
  error = {
55 298fe380 Iustin Pop
    "success": False,
56 298fe380 Iustin Pop
    "info": text,
57 538475ca Iustin Pop
    "nodes": [],
58 298fe380 Iustin Pop
    }
59 298fe380 Iustin Pop
  print simplejson.dumps(error, indent=2)
60 538475ca Iustin Pop
  return exit_code
61 298fe380 Iustin Pop
62 298fe380 Iustin Pop
63 298fe380 Iustin Pop
def main():
64 298fe380 Iustin Pop
  """Main function.
65 298fe380 Iustin Pop
66 298fe380 Iustin Pop
  """
67 298fe380 Iustin Pop
  if len(sys.argv) < 2:
68 298fe380 Iustin Pop
    print >> sys.stderr, "Usage: %s cluster.json" % (sys.argv[0])
69 298fe380 Iustin Pop
    return 1
70 298fe380 Iustin Pop
71 298fe380 Iustin Pop
  data = simplejson.load(open(sys.argv[1]))
72 298fe380 Iustin Pop
73 298fe380 Iustin Pop
  nodes =  data["nodes"]
74 298fe380 Iustin Pop
  request = data["request"]
75 298fe380 Iustin Pop
  req_type = request["type"]
76 eb0994e7 Iustin Pop
  if req_type == "allocate":
77 eb0994e7 Iustin Pop
    forbidden_nodes = []
78 eb0994e7 Iustin Pop
    inst_data = request
79 2a139bb0 Iustin Pop
  elif req_type == "relocate":
80 eb0994e7 Iustin Pop
    idict = data["instances"][request["name"]]
81 eb0994e7 Iustin Pop
    forbidden_nodes = idict["nodes"]
82 eb0994e7 Iustin Pop
    inst_data = idict
83 eb0994e7 Iustin Pop
    inst_data["disk_space_total"] = request["disk_space_total"]
84 eb0994e7 Iustin Pop
  else:
85 27579978 Iustin Pop
    return OutputError("Unsupported allocator mode '%s'" % req_type)
86 27579978 Iustin Pop
87 27579978 Iustin Pop
  result_nodes = []
88 27579978 Iustin Pop
  while len(result_nodes) < request["required_nodes"]:
89 eb0994e7 Iustin Pop
    new_selection = SelectNode(nodes, inst_data, result_nodes+forbidden_nodes)
90 27579978 Iustin Pop
    if new_selection is None:
91 27579978 Iustin Pop
      return OutputError("Can't find a suitable node for position %s"
92 27579978 Iustin Pop
                         " (already selected: %s)" %
93 27579978 Iustin Pop
                         (len(result_nodes) + 1, ", ".join(result_nodes)),
94 27579978 Iustin Pop
                         exit_code=0)
95 27579978 Iustin Pop
    result_nodes.append(new_selection)
96 298fe380 Iustin Pop
97 298fe380 Iustin Pop
  result = {
98 298fe380 Iustin Pop
          "success": True,
99 298fe380 Iustin Pop
          "info": "Allocation successful",
100 298fe380 Iustin Pop
          "nodes": result_nodes,
101 298fe380 Iustin Pop
          }
102 298fe380 Iustin Pop
  print simplejson.dumps(result, indent=2)
103 298fe380 Iustin Pop
  return 0
104 298fe380 Iustin Pop
105 298fe380 Iustin Pop
if __name__ == "__main__":
106 298fe380 Iustin Pop
    sys.exit(main())