Add the renumber remctl 0.4.21
authorMitchell E Berger <mitchb@mit.edu>
Sun, 27 May 2018 03:42:50 +0000 (23:42 -0400)
committerMitchell E Berger <mitchb@mit.edu>
Sun, 27 May 2018 03:42:50 +0000 (23:42 -0400)
debian/changelog
server/usr/sbin/invirt-remote-control

index ba2843f..7506e4c 100644 (file)
@@ -1,6 +1,7 @@
 invirt-remote (0.4.21) precise; urgency=low
 
   * Add the long-awaited arp remctl
+  * Add the renumber remctl
 
  -- Mitchell Berger <mitchb@mit.edu>  Fri, 18 May 2018 04:08:00 -0400
 
index b205760..eff4c3c 100755 (executable)
@@ -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 <machine> <command>"
@@ -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))