root / doc / examples / dumb-allocator @ 752a8ca8
History | View | Annotate | Download (3.1 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 | 1325da74 | Iustin Pop | offline_nodes = [name for name in nodes if nodes[name]["offline"]] |
78 | 7d26425f | Iustin Pop | drained_nodes = [name for name in nodes if nodes[name]["offline"]] |
79 | eb0994e7 | Iustin Pop | if req_type == "allocate": |
80 | 5c562aa4 | Guido Trotter | forbidden_nodes = offline_nodes + drained_nodes |
81 | eb0994e7 | Iustin Pop | inst_data = request |
82 | 2a139bb0 | Iustin Pop | elif req_type == "relocate": |
83 | eb0994e7 | Iustin Pop | idict = data["instances"][request["name"]] |
84 | 7d26425f | Iustin Pop | forbidden_nodes = idict["nodes"] + offline_nodes + drained_nodes |
85 | eb0994e7 | Iustin Pop | inst_data = idict |
86 | eb0994e7 | Iustin Pop | inst_data["disk_space_total"] = request["disk_space_total"] |
87 | eb0994e7 | Iustin Pop | else: |
88 | 27579978 | Iustin Pop | return OutputError("Unsupported allocator mode '%s'" % req_type) |
89 | 27579978 | Iustin Pop | |
90 | 27579978 | Iustin Pop | result_nodes = [] |
91 | 27579978 | Iustin Pop | while len(result_nodes) < request["required_nodes"]: |
92 | eb0994e7 | Iustin Pop | new_selection = SelectNode(nodes, inst_data, result_nodes+forbidden_nodes) |
93 | 27579978 | Iustin Pop | if new_selection is None: |
94 | 27579978 | Iustin Pop | return OutputError("Can't find a suitable node for position %s" |
95 | 27579978 | Iustin Pop | " (already selected: %s)" % |
96 | 27579978 | Iustin Pop | (len(result_nodes) + 1, ", ".join(result_nodes)), |
97 | 27579978 | Iustin Pop | exit_code=0) |
98 | 27579978 | Iustin Pop | result_nodes.append(new_selection) |
99 | 298fe380 | Iustin Pop | |
100 | 298fe380 | Iustin Pop | result = { |
101 | b3a447ef | Michael Hanselmann | "success": True, |
102 | b3a447ef | Michael Hanselmann | "info": "Allocation successful", |
103 | b3a447ef | Michael Hanselmann | "nodes": result_nodes, |
104 | b3a447ef | Michael Hanselmann | } |
105 | 298fe380 | Iustin Pop | print simplejson.dumps(result, indent=2) |
106 | 298fe380 | Iustin Pop | return 0 |
107 | 298fe380 | Iustin Pop | |
108 | b3a447ef | Michael Hanselmann | |
109 | 298fe380 | Iustin Pop | if __name__ == "__main__": |
110 | 298fe380 | Iustin Pop | sys.exit(main()) |