Add the renumber remctl
[invirt/packages/invirt-remote.git] / server / usr / sbin / invirt-remote-control
1 #!/usr/bin/python
2 """
3 Sends remctl commands about a running VM to the host it's running on.
4 """
5
6 from subprocess import PIPE, Popen, call
7 from invirt.database import connect, session, models
8 import sys
9 import time
10 import yaml
11
12 def find_vm(name):
13     p = Popen(['/usr/sbin/invirt-remote-proxy-web', 'listvms'], stdout=PIPE)
14     output = p.communicate()[0]
15     if p.returncode != 0:
16         raise RuntimeError("Command '%s' returned non-zero exit status %d"
17                            % ('invirt-remote-proxy-web', p.returncode)) 
18     vms= yaml.load(output, yaml.CSafeLoader)
19     return vms[name]['host'] if name in vms else None
20
21 def run_control_remctl(host, args, quiet=0):
22     p = Popen(['remctl', host, 'remote', 'control'] + args,
23               stdout=PIPE, stderr=PIPE)
24     (out, err) = p.communicate()
25     if not quiet:
26         if p.returncode == 1:
27             print >>sys.stderr, "machine '%s' is not on" % args[0]
28         elif p.returncode == 34:
29             print >>sys.stderr, "ERROR: invalid command"
30         sys.stderr.write(err)
31         sys.stdout.write(out)
32     return p.returncode
33
34 def main(argv):
35     if len(argv) < 3:
36         print >>sys.stderr, "usage: invirt-remote-control <machine> <command>"
37         return 2
38     machine_name = argv[1]
39     command = argv[2]
40
41     host = find_vm(machine_name)
42
43     if command == 'renumber':
44         connect()
45         machine = models.Machine.query.filter_by(name=machine_name).one()
46         renumber = 0
47         for n in machine.nics:
48             if n.other_action and n.other_action == 'renumber_dhcp':
49                 n.other_action = 'renumber'
50                 session.add(n)
51                 session.flush()
52                 renumber += 1
53                 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)
54             else:
55                 print 'IP %s is not currently slated to be renumbered.' % (n.ip)
56         if not renumber:
57             print >>sys.stderr, "machine '%s' is not currently slated to be renumbered" % (machine_name)
58             return 1
59         if not host:
60             print "'%s' does not appear to be running currently.  You should" % (machine_name)
61             print "turn it on and ensure that it is either configured to use"
62             print "DHCP or statically configured with the new IP address(es),"
63             print "netmask(s), and gateway(s) above, and verify that it is"
64             print "working as expected."
65             return 0
66         run_control_remctl(host, [machine_name, 'shutdown'])
67         ret = count = 0
68         # 'xm list' returns 3 when the domain doesn't exist
69         while count < 6 and ret != 3:
70             time.sleep(5)
71             # No sense using an expensive call to probe the whole cluster
72             # when we're just waiting for it to shut down and know where it is.
73             ret = run_control_remctl(host, [machine_name, 'list'], quiet=1)
74         if ret != 3:
75             print >>sys.stderr, "Could not shut down machine '%s' - you must turn it completely off, then turn it back on." % (machine_name)
76             return 2
77         print "Machine '%s' has been turned off.  It will now be turned back on." % (machine_name)
78         # Now we'll do the expensive call just to be sure the user didn't
79         # turn it on somewhere else while we were waiting, as the next step
80         # here would corrupt its disk.
81         if not find_vm(machine_name):
82             return run_control_remctl(host, [machine_name, 'create'])
83         # If the user turned it back on themselves, at this point, that's ok.
84         return 0
85
86     if not host:
87         print >>sys.stderr, "machine '%s' is not on" % machine_name
88         return 1
89
90     return run_control_remctl(host, argv[1:])
91
92 if __name__ == '__main__':
93     sys.exit(main(sys.argv))
94
95 # vim:et:sw=4:ts=4