#!/usr/bin/python """ Picks a host to "create" (boot) a VM on, and does so. Current load-balancing algorithm: wherever there's more free RAM. TODO: use a lock to avoid creating the same VM twice in a race """ from subprocess import PIPE, Popen, call import sys import yaml def choose_host(): # Query each of the hosts. # TODO get `servers` from a real list of all the VM hosts (instead of # hardcoding the list here) servers = ['black-mesa.mit.edu', 'sx-blade-2.mit.edu'] pipes = [(server, Popen(['remctl', server, 'remote', 'web', 'info'], stdout=PIPE)) for server in servers] outputs = [(s, p.communicate()[0]) for (s, p) in pipes] for (s, p) in pipes: if p.returncode != 0: raise RuntimeError("remctl to host %s returned non-zero exit status %d" % (s, p.returncode)) results = [(s, yaml.load(o, yaml.CSafeLoader)) for (s, o) in outputs] # XXX will the output of 'xm info' always be parseable YAML? return max( (int(o['free_memory']), s) for (s, o) in results )[1] def main(argv): if len(argv) < 2: print >>sys.stderr, "usage: sipb-xen-remote-create []" return 2 machine_name = argv[1] args = argv[2:] p = Popen(['/usr/sbin/sipb-xen-remote-proxy-web', 'listvms'], stdout=PIPE) output = p.communicate()[0] if p.returncode != 0: raise RuntimeError("Command '%s' returned non-zero exit status %d" % ('sipb-xen-remote-proxy-web', p.returncode)) vms = yaml.load(output, yaml.CSafeLoader) if machine_name in vms: host = vms[machine_name]['host'] print >>sys.stderr, ("machine '%s' is already running on host %s" % (machine_name, host)) return 1 host = choose_host() print 'Creating on host %s...' % host sys.stdout.flush() return call(['remctl', host, 'remote', 'control', machine_name, 'create'] + args) if __name__ == '__main__': sys.exit(main(sys.argv)) # vim:et:sw=4:ts=4