From fa8527190310e009d595321ad8267390085c3036 Mon Sep 17 00:00:00 2001 From: Mitchell E Berger Date: Sat, 26 May 2018 23:42:50 -0400 Subject: [PATCH] Add the renumber remctl --- debian/changelog | 1 + server/usr/sbin/invirt-remote-control | 90 +++++++++++++++++++++++++-------- 2 files changed, 71 insertions(+), 20 deletions(-) diff --git a/debian/changelog b/debian/changelog index ba2843f..7506e4c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ invirt-remote (0.4.21) precise; urgency=low * Add the long-awaited arp remctl + * Add the renumber remctl -- Mitchell Berger Fri, 18 May 2018 04:08:00 -0400 diff --git a/server/usr/sbin/invirt-remote-control b/server/usr/sbin/invirt-remote-control index b205760..eff4c3c 100755 --- a/server/usr/sbin/invirt-remote-control +++ b/server/usr/sbin/invirt-remote-control @@ -4,9 +4,33 @@ 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 " @@ -14,30 +38,56 @@ def main(argv): machine_name = argv[1] command = argv[2] - 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) + host = find_vm(machine_name) - if machine_name not in vms: - print >>sys.stderr, "machine '%s' is not on" % machine_name - return 1 - host = vms[machine_name]['host'] + 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 - p = Popen(['remctl', host, 'remote', 'control'] + argv[1:], - stdout=PIPE, stderr=PIPE) - (out, err) = p.communicate() - if p.returncode == 1: + if not host: print >>sys.stderr, "machine '%s' is not on" % machine_name return 1 - elif p.returncode == 34: - print >>sys.stderr, "ERROR: invalid command" - return 34 - sys.stderr.write(err) - sys.stdout.write(out) - return p.returncode + + return run_control_remctl(host, argv[1:]) if __name__ == '__main__': sys.exit(main(sys.argv)) -- 1.7.9.5