From: Greg Price Date: Sun, 29 Jun 2008 03:28:08 +0000 (-0400) Subject: code to load-balance boots among hosts X-Git-Tag: sipb-xen-remote-server/0.2~6 X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/invirt-remote.git/commitdiff_plain/15813cdf61c889aae4cc9b1d2eecbdf71869fb8a code to load-balance boots among hosts svn path=/trunk/packages/sipb-xen-remote-server/; revision=658 --- diff --git a/files/usr/sbin/sipb-xen-remote-create b/files/usr/sbin/sipb-xen-remote-create new file mode 100755 index 0000000..c4a62cc --- /dev/null +++ b/files/usr/sbin/sipb-xen-remote-create @@ -0,0 +1,68 @@ +#!/usr/bin/python +""" +Picks a host to "create" (boot) a VM on, and does so. + +For now, a very dumb algorithm for which host to boot on: +the one with fewer machines running. + +TODO: load-balance based on something like actual 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 + return call(['remctl', host, 'remote', 'control', + machine_name, 'create'] + args) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) + +# vim:et:sw=4:ts=4