#!/usr/bin/python """ Sends remctl commands about a running VM to the host it's running on. """ from subprocess import PIPE, Popen, call from invirt.database import connect, session, models import sys import time import yaml def find_vm(name): p = Popen(['/usr/sbin/invirt-remote-proxy-web', 'listvms'], stdout=PIPE) output = p.communicate()[0] if p.returncode != 0: raise RuntimeError("Command '%s' returned non-zero exit status %d" % ('invirt-remote-proxy-web', p.returncode)) vms= yaml.load(output, yaml.CSafeLoader) return vms[name]['host'] if name in vms else None def run_control_remctl(host, args, quiet=0): p = Popen(['remctl', host, 'remote', 'control'] + args, stdout=PIPE, stderr=PIPE) (out, err) = p.communicate() if not quiet: if p.returncode == 1: print >>sys.stderr, "machine '%s' is not on" % args[0] elif p.returncode == 34: print >>sys.stderr, "ERROR: invalid command" sys.stderr.write(err) sys.stdout.write(out) return p.returncode def main(argv): if len(argv) < 3: print >>sys.stderr, "usage: invirt-remote-control " return 2 machine_name = argv[1] command = argv[2] host = find_vm(machine_name) if command == 'renumber': connect() machine = models.Machine.query.filter_by(name=machine_name).one() renumber = 0 for n in machine.nics: if n.other_action and n.other_action == 'renumber_dhcp': n.other_action = 'renumber' session.add(n) session.flush() renumber += 1 print "IP %s is set to be renumbered to %s with netmask %s and gateway %s the next time '%s' is powered on." % (n.ip, n.other_ip, n.other_netmask, n.other_gateway, machine_name) else: print 'IP %s is not currently slated to be renumbered.' % (n.ip) if not renumber: print >>sys.stderr, "machine '%s' is not currently slated to be renumbered" % (machine_name) return 1 if not host: print "'%s' does not appear to be running currently. You should" % (machine_name) print "turn it on and ensure that it is either configured to use" print "DHCP or statically configured with the new IP address(es)," print "netmask(s), and gateway(s) above, and verify that it is" print "working as expected." return 0 run_control_remctl(host, [machine_name, 'shutdown']) ret = count = 0 # 'xm list' returns 3 when the domain doesn't exist while count < 6 and ret != 3: time.sleep(5) # No sense using an expensive call to probe the whole cluster # when we're just waiting for it to shut down and know where it is. ret = run_control_remctl(host, [machine_name, 'list'], quiet=1) if ret != 3: print >>sys.stderr, "Could not shut down machine '%s' - you must turn it completely off, then turn it back on." % (machine_name) return 2 print "Machine '%s' has been turned off. It will now be turned back on." % (machine_name) # Now we'll do the expensive call just to be sure the user didn't # turn it on somewhere else while we were waiting, as the next step # here would corrupt its disk. if not find_vm(machine_name): return run_control_remctl(host, [machine_name, 'create']) # If the user turned it back on themselves, at this point, that's ok. return 0 if not host: print >>sys.stderr, "machine '%s' is not on" % machine_name return 1 return run_control_remctl(host, argv[1:]) if __name__ == '__main__': sys.exit(main(sys.argv)) # vim:et:sw=4:ts=4