From: Mitchell E Berger Date: Fri, 18 May 2018 18:40:27 +0000 (-0400) Subject: Add the renumber remctl. X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/invirt-remote.git/commitdiff_plain/refs/heads/mitchb-renumber-remctl Add the renumber remctl. NOTE: The code currently performs as expected, but the functionality has a still-undiagnosed problem, so this can't be used yet. --- 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/host/usr/sbin/invirt-vmcontrol b/host/usr/sbin/invirt-vmcontrol index eaac5ac..43b3449 100755 --- a/host/usr/sbin/invirt-vmcontrol +++ b/host/usr/sbin/invirt-vmcontrol @@ -57,6 +57,40 @@ case "$ACTION" in fi done ;; + renumber) + shift; shift; + curip="$1" + curgw="$2" + newip="$3" + newgw="$4" + xs_prefix="/local/domain/0/backend/vif" + domid=`xm domid $MACHINE` + renumbered= + for vif in `xenstore-list $xs_prefix/$domid`; do + ip=`xenstore-read $xs_prefix/$domid/$vif/ip` + if [ $ip == $curip ]; then + script=`xenstore-read $xs_prefix/$domid/$vif/script` + # If the domain is rebooted without a full shutdown, the + # invirt-database script doesn't run to fill in arguments for + # vif-invirtroute, so we need to rewrite it as if it had + # been booted with the IP parameters swapped. + script=`echo $script | sed -ne "s/\(.* netdev=[^ ]*\).*/\1 gateway=$newgw other_ip=$curip other_gateway=$curgw/p"` + # The sed above will only print something if we matched. If + # the content of the script key wasn't as we expected, don't + # mess with it. + if [ -n "$script" ]; then + xenstore-write $xs_prefix/$domid/$vif/script "$script" + echo "'$ORIGMACHINE' has been configured to renumber $curip to $newip if it is rebooted without being powered off." + renumbered=yes + fi + fi + done + if [ -n "$renumbered" ]; then + echo "XVM's DNS server has been updated with your new address information." + echo "You MUST reboot your VM immediately in order for it to respond properly" + echo "to the old and new addresses." + fi + ;; *) echo "ERROR: Invalid Command" exit 34 diff --git a/server/usr/sbin/invirt-remote-control b/server/usr/sbin/invirt-remote-control index b205760..68335ca 100755 --- a/server/usr/sbin/invirt-remote-control +++ b/server/usr/sbin/invirt-remote-control @@ -4,6 +4,7 @@ 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 yaml @@ -14,6 +15,40 @@ def main(argv): machine_name = argv[1] command = argv[2] + renumber = [] + if command == 'renumber': + connect() + machine = models.Machine.query.filter_by(name=machine_name).one() + for n in machine.nics: + if n.other_action and n.other_action == 'renumber_dhcp': + renumber.append((n.ip, n.gateway, n.other_ip, n.other_gateway)) + print "IP %s is set to be renumbered to %s the next time '%s' is powered on." % (n.ip, n.other_ip, machine_name) + # We have to switch this now; we can't simply change to the + # 'renumber' state, because that will only work if the machine + # is turned off fully and then turned back on. A reboot will + # only run vif-invirtroute, not invirt-database, so we need + # to edit the vif-invirtroute script parameters in xenstore + # if the machine is on. That's why we have just saved a + # tuple of parameters, which we will pass to a host-based + # remctl if the machine is actually on (further below in this + # script). As a consequence of us swapping this now, DNS + # will change when the user runs this remctl, so if the machine + # is on, they will need to reboot it promptly to begin + # responding to the new address. We don't know if it's on + # yet, or if we'll succeed in editing the script. The + # remctl from the host will warn them to reboot immediately + # if successful. + (n.ip, n.netmask, n.gateway, + n.other_ip, n.other_netmask, n.other_gateway, n.other_action) = ( + n.other_ip, n.other_netmask, n.other_gateway, + n.ip, n.netmask, n.gateway, 'dnat') + session.add(n) + session.flush() + 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 p = Popen(['/usr/sbin/invirt-remote-proxy-web', 'listvms'], stdout=PIPE) output = p.communicate()[0] if p.returncode != 0: @@ -22,10 +57,32 @@ def main(argv): vms = yaml.load(output, yaml.CSafeLoader) if machine_name not in vms: + if renumber: + # It's okay for the machine not to be on with the 'renumber' + # remctl. There's a DB component of the work (completed above) + # and an adjustment to make to the machine if it happens to be on. + return 0 print >>sys.stderr, "machine '%s' is not on" % machine_name return 1 host = vms[machine_name]['host'] + if renumber: + # We need to pass parameters from the database that the remctl script + # on the host where the VM is running won't easily have access to, and + # we may need to do this for multiple NICs, so we'll do this in our + # own loop for the 'renumber' remctl, separate from the normal remote + # control code path. + for nicparams in renumber: + p = Popen(['remctl', host, 'remote', 'control'] + argv[1:] + list(nicparams), + stdout=PIPE, stderr=PIPE) + (out, err) = p.communicate() + if p.returncode == 1: + print >>sys.stderr, "machine '%s' is not on" % machine_name + return 1 + sys.stderr.write(err) + sys.stdout.write(out) + return 0 + p = Popen(['remctl', host, 'remote', 'control'] + argv[1:], stdout=PIPE, stderr=PIPE) (out, err) = p.communicate()