Connect vif's to already running VMs on NetVM/ProxyVM startup (#190)

Also cleanup stale vifs using "xm network-detach ... -f"
Fix iptables rules to support not only first vif of VM
This commit is contained in:
Marek Marczykowski 2011-04-23 02:32:54 +02:00
parent 655f13e2ec
commit 98f4028142
3 changed files with 62 additions and 9 deletions

View File

@ -5,7 +5,8 @@ netmask=`/usr/bin/xenstore-read qubes_netmask`
gateway=`/usr/bin/xenstore-read qubes_gateway`
secondary_dns=`/usr/bin/xenstore-read qubes_secondary_dns`
if [ x$ip != x ]; then
/sbin/ifconfig $INTERFACE $ip netmask 255.255.255.255 up
/sbin/ifconfig $INTERFACE $ip netmask 255.255.255.255
/sbin/ifconfig $INTERFACE up
/sbin/route add default dev $INTERFACE
echo "nameserver $gateway" > /etc/resolv.conf
echo "nameserver $secondary_dns" >> /etc/resolv.conf

View File

@ -543,6 +543,28 @@ class QubesVm(object):
f_private.truncate (size)
f_private.close ()
def cleanup_vifs(self):
"""
Xend does not remove vif when backend domain is down, so we must do it
manually
"""
if not self.is_running():
return
p = subprocess.Popen (["/usr/sbin/xm", "network-list", self.name],
stdout=subprocess.PIPE)
result = p.communicate()
for line in result[0].split('\n'):
m = re.match(r"^(\d+)\s*(\d+)", line)
if m:
retcode = subprocess.call(["/usr/sbin/xm", "list", m.group(2)],
stderr=subprocess.PIPE)
if retcode != 0:
# Don't check retcode - it always will fail when backend domain is down
subprocess.call(["/usr/sbin/xm",
"network-detach", self.name, m.group(1), "-f"], stderr=subprocess.PIPE)
def create_xenstore_entries(self, xid):
if dry_run:
return
@ -1371,6 +1393,29 @@ class QubesNetVm(QubesVm):
return subprocess.check_call(command)
def start(self, debug_console = False, verbose = False, preparing_dvm=False):
if dry_run:
return
xid=super(QubesNetVm, self).start(debug_console=debug_console, verbose=verbose)
# Connect vif's of already running VMs
for vm in self.connected_vms.values():
if not vm.is_running():
continue
if verbose:
print "--> Attaching network to '{0}'...".format(vm.name)
# Cleanup stale VIFs
vm.cleanup_vifs()
xm_cmdline = ["/usr/sbin/xm", "network-attach", vm.name, "script=vif-route-qubes", "ip="+vm.ip, "backend="+self.name ]
retcode = subprocess.call (xm_cmdline)
if retcode != 0:
print ("WARNING: Cannot attach to network to '{0}'!".format(vm.name))
return xid
def add_external_ip_permission(self, xid):
if int(xid) < 0:
return
@ -1471,7 +1516,7 @@ class QubesProxyVm(QubesNetVm):
continue
iptables += "# '{0}' VM:\n".format(vm.name)
iptables += "-A FORWARD ! -s {0}/32 -i vif{1}.0 -j DROP\n".format(vm.ip, xid)
iptables += "-A FORWARD ! -s {0}/32 -i vif{1}.+ -j DROP\n".format(vm.ip, xid)
accept_action = "ACCEPT"
reject_action = "REJECT --reject-with icmp-host-prohibited"
@ -1484,7 +1529,7 @@ class QubesProxyVm(QubesNetVm):
rules_action = accept_action
for rule in conf["rules"]:
iptables += "-A FORWARD -i vif{0}.0 -d {1}".format(xid, rule["address"])
iptables += "-A FORWARD -i vif{0}.+ -d {1}".format(xid, rule["address"])
if rule["netmask"] != 32:
iptables += "/{0}".format(rule["netmask"])
@ -1497,12 +1542,12 @@ class QubesProxyVm(QubesNetVm):
if conf["allowDns"]:
# PREROUTING does DNAT to NetVM DNSes, so we need self.netvm_vm. properties
iptables += "-A FORWARD -i vif{0}.0 -p udp -d {1} --dport 53 -j ACCEPT\n".format(xid,self.netvm_vm.gateway)
iptables += "-A FORWARD -i vif{0}.0 -p udp -d {1} --dport 53 -j ACCEPT\n".format(xid,self.netvm_vm.secondary_dns)
iptables += "-A FORWARD -i vif{0}.+ -p udp -d {1} --dport 53 -j ACCEPT\n".format(xid,self.netvm_vm.gateway)
iptables += "-A FORWARD -i vif{0}.+ -p udp -d {1} --dport 53 -j ACCEPT\n".format(xid,self.netvm_vm.secondary_dns)
if conf["allowIcmp"]:
iptables += "-A FORWARD -i vif{0}.0 -p icmp -j ACCEPT\n".format(xid)
iptables += "-A FORWARD -i vif{0}.+ -p icmp -j ACCEPT\n".format(xid)
iptables += "-A FORWARD -i vif{0}.0 -j {1}\n".format(xid, default_action)
iptables += "-A FORWARD -i vif{0}.+ -j {1}\n".format(xid, default_action)
iptables += "#End of VM rules\n"
iptables += "-A FORWARD -j DROP\n"

View File

@ -166,6 +166,9 @@ def main():
parser.add_option ("--localcmd", action="store", dest="localcmd", default=None,
help="With --pass_io, pass stdin/stdout/stderr to the given program")
parser.add_option ("--force", action="store_true", dest="force", default=False,
help="Force operation, even if may damage other VMs (eg shutdown of NetVM)")
(options, args) = parser.parse_args ()
@ -218,8 +221,12 @@ def main():
# If stopping NetVM - stop connected VMs too
if options.shutdown and vm.is_netvm():
vms_list += [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()]
vms_list.reverse()
connected_vms = [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()]
if connected_vms and not options.force:
print "ERROR: There are other VMs connected to this VM, "
print " shutdown them first or use --force option"
print "VMs list: " + str([vm.name for vm in connected_vms])
exit(1)
if takes_cmd_argument:
cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr)