root / doc / examples / dumb-allocator @ 298fe380
History | View | Annotate | Download (2.6 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 | 298fe380 | Iustin Pop | def OutputError(text): |
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 | 298fe380 | Iustin Pop | } |
58 | 298fe380 | Iustin Pop | print simplejson.dumps(error, indent=2) |
59 | 298fe380 | Iustin Pop | return 1 |
60 | 298fe380 | Iustin Pop | |
61 | 298fe380 | Iustin Pop | |
62 | 298fe380 | Iustin Pop | def main(): |
63 | 298fe380 | Iustin Pop | """Main function. |
64 | 298fe380 | Iustin Pop | |
65 | 298fe380 | Iustin Pop | """ |
66 | 298fe380 | Iustin Pop | if len(sys.argv) < 2: |
67 | 298fe380 | Iustin Pop | print >> sys.stderr, "Usage: %s cluster.json" % (sys.argv[0]) |
68 | 298fe380 | Iustin Pop | return 1 |
69 | 298fe380 | Iustin Pop | |
70 | 298fe380 | Iustin Pop | data = simplejson.load(open(sys.argv[1])) |
71 | 298fe380 | Iustin Pop | |
72 | 298fe380 | Iustin Pop | nodes = data["nodes"] |
73 | 298fe380 | Iustin Pop | request = data["request"] |
74 | 298fe380 | Iustin Pop | req_type = request["type"] |
75 | 298fe380 | Iustin Pop | if req_type != "allocate": |
76 | 298fe380 | Iustin Pop | print >> sys.stderr, "Unsupported allocator mode '%s'" % req_type |
77 | 298fe380 | Iustin Pop | return 1 |
78 | 298fe380 | Iustin Pop | |
79 | 298fe380 | Iustin Pop | npri = SelectNode(nodes, request, []) |
80 | 298fe380 | Iustin Pop | if npri is None: |
81 | 298fe380 | Iustin Pop | return OutputError("Can't find a suitable primary node") |
82 | 298fe380 | Iustin Pop | |
83 | 298fe380 | Iustin Pop | result_nodes = [npri] |
84 | 298fe380 | Iustin Pop | if request["disk_template"] == "drbd": |
85 | 298fe380 | Iustin Pop | nsec = SelectNode(nodes, request, result_nodes) |
86 | 298fe380 | Iustin Pop | if nsec is None: |
87 | 298fe380 | Iustin Pop | return OutputError("Can't find a suitable secondary node (%s selected" |
88 | 298fe380 | Iustin Pop | " as primary)" % npri) |
89 | 298fe380 | Iustin Pop | result_nodes.append(nsec) |
90 | 298fe380 | Iustin Pop | |
91 | 298fe380 | Iustin Pop | result = { |
92 | 298fe380 | Iustin Pop | "success": True, |
93 | 298fe380 | Iustin Pop | "info": "Allocation successful", |
94 | 298fe380 | Iustin Pop | "nodes": result_nodes, |
95 | 298fe380 | Iustin Pop | } |
96 | 298fe380 | Iustin Pop | print simplejson.dumps(result, indent=2) |
97 | 298fe380 | Iustin Pop | return 0 |
98 | 298fe380 | Iustin Pop | |
99 | 298fe380 | Iustin Pop | if __name__ == "__main__": |
100 | 298fe380 | Iustin Pop | sys.exit(main()) |