Statistics
| Branch: | Tag: | Revision:

root / doc / examples / dumb-allocator @ 4300c4b6

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 b3a447ef Michael Hanselmann
29 298fe380 Iustin Pop
import simplejson
30 298fe380 Iustin Pop
import sys
31 298fe380 Iustin Pop
32 298fe380 Iustin Pop
33 298fe380 Iustin Pop
def SelectNode(nodes, request, to_skip):
34 298fe380 Iustin Pop
  """Select a node for the given instance
35 298fe380 Iustin Pop
36 298fe380 Iustin Pop
  """
37 298fe380 Iustin Pop
  disk_size = request["disk_space_total"]
38 298fe380 Iustin Pop
  selected = None
39 298fe380 Iustin Pop
  for nname, ninfo in nodes.iteritems():
40 298fe380 Iustin Pop
    if nname in to_skip:
41 298fe380 Iustin Pop
      continue
42 298fe380 Iustin Pop
    if request["memory"] > ninfo["free_memory"]:
43 298fe380 Iustin Pop
      continue
44 298fe380 Iustin Pop
    if disk_size > ninfo["free_disk"]:
45 298fe380 Iustin Pop
      continue
46 298fe380 Iustin Pop
    selected = nname
47 298fe380 Iustin Pop
    break
48 298fe380 Iustin Pop
  return selected
49 298fe380 Iustin Pop
50 298fe380 Iustin Pop
51 538475ca Iustin Pop
def OutputError(text, exit_code=1):
52 298fe380 Iustin Pop
  """Builds an error response with a given info message.
53 298fe380 Iustin Pop
54 298fe380 Iustin Pop
  """
55 298fe380 Iustin Pop
  error = {
56 298fe380 Iustin Pop
    "success": False,
57 298fe380 Iustin Pop
    "info": text,
58 538475ca Iustin Pop
    "nodes": [],
59 298fe380 Iustin Pop
    }
60 298fe380 Iustin Pop
  print simplejson.dumps(error, indent=2)
61 538475ca Iustin Pop
  return exit_code
62 298fe380 Iustin Pop
63 298fe380 Iustin Pop
64 298fe380 Iustin Pop
def main():
65 298fe380 Iustin Pop
  """Main function.
66 298fe380 Iustin Pop
67 298fe380 Iustin Pop
  """
68 298fe380 Iustin Pop
  if len(sys.argv) < 2:
69 298fe380 Iustin Pop
    print >> sys.stderr, "Usage: %s cluster.json" % (sys.argv[0])
70 298fe380 Iustin Pop
    return 1
71 298fe380 Iustin Pop
72 298fe380 Iustin Pop
  data = simplejson.load(open(sys.argv[1]))
73 298fe380 Iustin Pop
74 298fe380 Iustin Pop
  nodes =  data["nodes"]
75 298fe380 Iustin Pop
  request = data["request"]
76 298fe380 Iustin Pop
  req_type = request["type"]
77 eb0994e7 Iustin Pop
  if req_type == "allocate":
78 eb0994e7 Iustin Pop
    forbidden_nodes = []
79 eb0994e7 Iustin Pop
    inst_data = request
80 2a139bb0 Iustin Pop
  elif req_type == "relocate":
81 eb0994e7 Iustin Pop
    idict = data["instances"][request["name"]]
82 eb0994e7 Iustin Pop
    forbidden_nodes = idict["nodes"]
83 eb0994e7 Iustin Pop
    inst_data = idict
84 eb0994e7 Iustin Pop
    inst_data["disk_space_total"] = request["disk_space_total"]
85 eb0994e7 Iustin Pop
  else:
86 27579978 Iustin Pop
    return OutputError("Unsupported allocator mode '%s'" % req_type)
87 27579978 Iustin Pop
88 27579978 Iustin Pop
  result_nodes = []
89 27579978 Iustin Pop
  while len(result_nodes) < request["required_nodes"]:
90 eb0994e7 Iustin Pop
    new_selection = SelectNode(nodes, inst_data, result_nodes+forbidden_nodes)
91 27579978 Iustin Pop
    if new_selection is None:
92 27579978 Iustin Pop
      return OutputError("Can't find a suitable node for position %s"
93 27579978 Iustin Pop
                         " (already selected: %s)" %
94 27579978 Iustin Pop
                         (len(result_nodes) + 1, ", ".join(result_nodes)),
95 27579978 Iustin Pop
                         exit_code=0)
96 27579978 Iustin Pop
    result_nodes.append(new_selection)
97 298fe380 Iustin Pop
98 298fe380 Iustin Pop
  result = {
99 b3a447ef Michael Hanselmann
    "success": True,
100 b3a447ef Michael Hanselmann
    "info": "Allocation successful",
101 b3a447ef Michael Hanselmann
    "nodes": result_nodes,
102 b3a447ef Michael Hanselmann
    }
103 298fe380 Iustin Pop
  print simplejson.dumps(result, indent=2)
104 298fe380 Iustin Pop
  return 0
105 298fe380 Iustin Pop
106 b3a447ef Michael Hanselmann
107 298fe380 Iustin Pop
if __name__ == "__main__":
108 298fe380 Iustin Pop
    sys.exit(main())