Whoops - I should actually check code after I write it; fix the new RemConfFS
[invirt/packages/invirt-remote.git] / files / usr / sbin / sipb-xen-remote-create
1 #!/usr/bin/python
2
3 """
4 Picks a host to "create" (boot) a VM on, and does so.
5
6 Current load-balancing algorithm: wherever there's more free RAM.
7
8 TODO: use a lock to avoid creating the same VM twice in a race
9 """
10
11 from invirt.remote import bcast
12 from subprocess import PIPE, Popen, call
13 import sys
14 import yaml
15
16 def choose_host():
17     # Query each of the hosts.
18     # XXX will the output of 'xm info' always be parseable YAML?
19     results = bcast('info')
20     return max((int(o['free_memory']), s) for (s, o) in results)[1]
21
22 def main(argv):
23     if len(argv) < 2:
24         print >> sys.stderr, "usage: sipb-xen-remote-create <machine> [<other args...>]"
25         return 2
26     machine_name = argv[1]
27     args = argv[2:]
28
29     p = Popen(['/usr/sbin/sipb-xen-remote-proxy-web', 'listvms'], stdout=PIPE)
30     output = p.communicate()[0]
31     if p.returncode != 0:
32         raise RuntimeError("Command '%s' returned non-zero exit status %d"
33                            % ('sipb-xen-remote-proxy-web', p.returncode)) 
34     vms = yaml.load(output, yaml.CSafeLoader)
35
36     if machine_name in vms:
37         host = vms[machine_name]['host']
38         print >> sys.stderr, ("machine '%s' is already running on host %s"
39                               % (machine_name, host))
40         return 1
41
42     host = choose_host()
43     print 'Creating on host %s...' % host
44     sys.stdout.flush()
45     return call(['remctl', host, 'remote', 'control',
46                  machine_name, 'create'] + args)
47
48 if __name__ == '__main__':
49     sys.exit(main(sys.argv))
50
51 # vim:et:sw=4:ts=4