diff --git a/dom0/qvm-core/qubes.py b/dom0/qvm-core/qubes.py index 1bdc8ba5..e9193616 100755 --- a/dom0/qvm-core/qubes.py +++ b/dom0/qvm-core/qubes.py @@ -239,7 +239,7 @@ class QubesVm(object): "template_vm": { "default": None, 'order': 10 }, # order >= 20: have template set "uses_default_netvm": { "default": True, 'order': 20 }, - "netvm": { "default": None, 'order': 20 }, + "netvm": { "default": None, "attr": "_netvm", 'order': 20 }, "label": { "attr": "_label", "default": QubesVmLabels["red"], 'order': 20 }, "memory": { "default": default_memory, 'order': 20 }, "maxmem": { "default": None, 'order': 25 }, @@ -376,6 +376,47 @@ class QubesVm(object): os.symlink (new_label.icon_path, self.icon_path) subprocess.call(['sudo', 'xdg-icon-resource', 'forceupdate']) + @property + def netvm(self): + return self._netvm + + # Don't know how properly call setter from base class, so workaround it... + @netvm.setter + def netvm(self, new_netvm): + self._set_netvm(new_netvm) + + def _set_netvm(self, new_netvm): + if self.netvm is not None: + self.netvm.connected_vms.pop(self.qid) + if self.is_running(): + subprocess.call(["xl", "network-detach", self.name, "0"], stderr=subprocess.PIPE) + if hasattr(self.netvm, 'post_vm_net_detach'): + self.netvm.post_vm_net_detach(self) + + if new_netvm is None: + # Set also firewall to block all traffic as discussed in #370 + if os.path.exists(self.firewall_conf): + shutil.copy(self.firewall_conf, "%s/backup/%s-firewall-%s.xml" + % (qubes_base_dir, self.name, time.strftime('%Y-%m-%d-%H:%M:%S'))) + self.write_firewall_conf({'allow': False, 'allowDns': False, + 'allowIcmp': False, 'rules': []}) + else: + new_netvm.connected_vms[self.qid]=self + + self._netvm = new_netvm + + if new_netvm is None: + return + + if self.is_running(): + if not new_netvm.is_running(): + new_netvm.start() + # refresh IP, DNS etc + self.create_xenstore_entries() + self.attach_network() + if hasattr(self.netvm, 'post_vm_net_attach'): + self.netvm.post_vm_net_attach(self) + @property def ip(self): if self.netvm is not None: @@ -448,22 +489,6 @@ class QubesVm(object): raise QubesException ("Change 'updateable' flag is not supported. Please use qvm-create.") - def set_netvm(self, netvm): - if self.netvm is not None: - self.netvm.connected_vms.pop(self.qid) - - if netvm is None: - # Set also firewall to block all traffic as discussed in #370 - if os.path.exists(self.firewall_conf): - shutil.copy(self.firewall_conf, "%s/backup/%s-firewall-%s.xml" - % (qubes_base_dir, self.name, time.strftime('%Y-%m-%d-%H:%M:%S'))) - self.write_firewall_conf({'allow': False, 'allowDns': False, - 'allowIcmp': False, 'rules': []}) - else: - netvm.connected_vms[self.qid]=self - - self.netvm = netvm - def pre_rename(self, new_name): pass @@ -1825,6 +1850,25 @@ class QubesProxyVm(QubesNetVm): def type(self): return "ProxyVM" + def _set_netvm(self, new_netvm): + old_netvm = self.netvm + super(QubesProxyVm, self)._set_netvm(new_netvm) + if self.netvm is not None: + self.netvm.add_external_ip_permission(self.get_xid()) + self.write_netvm_domid_entry() + if old_netvm is not None: + old_netvm.remove_external_ip_permission(self.get_xid()) + + def post_vm_net_attach(self, vm): + """ Called after some VM net-attached to this ProxyVm """ + + self.write_iptables_xenstore_entry() + + def post_vm_net_detach(self, vm): + """ Called after some VM net-detached from this ProxyVm """ + + self.write_iptables_xenstore_entry() + def start(self, debug_console = False, verbose = False, preparing_dvm = False): if dry_run: return @@ -2724,7 +2768,8 @@ class QubesVmCollection(dict): else: netvm = self[netvm_qid] - vm.netvm = netvm + # directly set internal attr to not call setters... + vm._netvm = netvm if netvm: netvm.connected_vms[vm.qid] = vm diff --git a/dom0/qvm-core/qubesutils.py b/dom0/qvm-core/qubesutils.py index d1690505..e9e0897f 100644 --- a/dom0/qvm-core/qubesutils.py +++ b/dom0/qvm-core/qubesutils.py @@ -135,8 +135,12 @@ def block_name_to_majorminor(name): elif name.startswith("sr"): disk = False major = 11 + elif name.startswith("md"): + disk = False + major = 9 else: - raise QubesException("Unknown device type %s" % name_match.group(1)) + # Unknown device + return (0, 0) if disk: minor = (ord(name_match.group(2))-ord('a')) * 16 @@ -211,6 +215,10 @@ def block_list(vm = None): if not mode_re.match(device_mode): print >> sys.stderr, "Invalid %s device mode in VM '%s'" % (device, vm_name) continue + # Check if we know major number for this device; attach will work without this, but detach and check_attached don't + if block_name_to_majorminor(device) == (0, 0): + print >> sys.stderr, "Unsupported device %s:%s" % (vm_name, device) + continue visible_name = "%s:%s" % (vm_name, device) devices_list[visible_name] = {"name": visible_name, "xid":int(xid), "vm": vm_name, "device":device, "size":int(device_size), diff --git a/dom0/qvm-tools/qvm-prefs b/dom0/qvm-tools/qvm-prefs index 719ff26e..046b1463 100755 --- a/dom0/qvm-tools/qvm-prefs +++ b/dom0/qvm-tools/qvm-prefs @@ -159,18 +159,7 @@ def set_netvm(vms, vm, args): exit (1) vm.uses_default_netvm = False - vm.set_netvm(netvm) - if not vm.is_running(): - return - # this can fail if VM was not connected to any NetVM - subprocess.call(["xl", "network-detach", vm.name, "0"], stderr=subprocess.PIPE) - if vm.netvm is None: - return - if not vm.netvm.is_running(): - subprocess.check_call(["qvm-start", vm.netvm.name]) - # refresh IP, DNS etc - vm.create_xenstore_entries() - vm.attach_network(verbose = True) + vm.netvm = netvm def set_updateable(vms, vm, args): if vm.is_updateable(): diff --git a/network/qubes_firewall b/network/qubes_firewall index 81dbca7c..30670b82 100755 --- a/network/qubes_firewall +++ b/network/qubes_firewall @@ -12,13 +12,20 @@ echo $$ >$PIDFILE trap 'exit 0' SIGTERM +FIRST_TIME=yes + while true; do echo "1" > /proc/sys/net/ipv4/ip_forward - # Wait for changes in xenstore file - /usr/bin/xenstore-watch-qubes $XENSTORE_IPTABLES - TRIGGER=$(/usr/bin/xenstore-read $XENSTORE_IPTABLES) + if [ "$FIRST_TIME" ]; then + FIRST_TIME= + TRIGGER=reload + else + # Wait for changes in xenstore file + /usr/bin/xenstore-watch-qubes $XENSTORE_IPTABLES + TRIGGER=$(/usr/bin/xenstore-read $XENSTORE_IPTABLES) + fi if ! [ "$TRIGGER" = "reload" ]; then continue ; fi diff --git a/network/qubes_netwatcher b/network/qubes_netwatcher index afd7cdaa..2512f737 100755 --- a/network/qubes_netwatcher +++ b/network/qubes_netwatcher @@ -18,14 +18,14 @@ while true; do # thus, no sanitization ready # but be careful when passing it to other shell scripts if [[ "$UNTRUSTED_NETCFG" != "$CURR_NETCFG" ]]; then - /sbin/service qubes_firewall stop - /sbin/service qubes_firewall start + /sbin/service qubes-firewall stop + /sbin/service qubes-firewall start CURR_NETCFG="$UNTRUSTED_NETCFG" /usr/bin/xenstore-write qubes_netvm_external_ip "$CURR_NETCFG" fi - /usr/bin/xenstore-watch-qubes /local/domain/$NET_DOMID/qubes_netvm_external_ip + /usr/bin/xenstore-watch -n 3 /local/domain/$NET_DOMID/qubes_netvm_external_ip qubes_netvm_domid else - /usr/bin/xenstore-watch-qubes qubes_netvm_domid + /usr/bin/xenstore-watch -n 2 qubes_netvm_domid fi done diff --git a/rpm_spec/core-vm.spec b/rpm_spec/core-vm.spec index f02cdccf..c11b699d 100644 --- a/rpm_spec/core-vm.spec +++ b/rpm_spec/core-vm.spec @@ -411,8 +411,8 @@ The Qubes core startup configuration for SysV init (or upstart). /etc/init.d/qubes_core /etc/init.d/qubes_core_appvm /etc/init.d/qubes_core_netvm -/etc/init.d/qubes_firewall -/etc/init.d/qubes_netwatcher +/etc/init.d/qubes-firewall +/etc/init.d/qubes-netwatcher %post sysvinit @@ -443,8 +443,8 @@ chkconfig --add qubes_core_appvm || echo "WARNING: Cannot add service qubes_core chkconfig qubes_core_appvm on || echo "WARNING: Cannot enable service qubes_core!" chkconfig --add qubes_firewall || echo "WARNING: Cannot add service qubes_core!" chkconfig qubes_firewall on || echo "WARNING: Cannot enable service qubes_core!" -chkconfig --add qubes_netwatcher || echo "WARNING: Cannot add service qubes_core!" -chkconfig qubes_netwatcher on || echo "WARNING: Cannot enable service qubes_core!" +chkconfig --add qubes-netwatcher || echo "WARNING: Cannot add service qubes_core!" +chkconfig qubes-netwatcher on || echo "WARNING: Cannot enable service qubes_core!" # TODO: make this not display the silly message about security context... sed -i s/^id:.:initdefault:/id:3:initdefault:/ /etc/inittab @@ -455,8 +455,8 @@ if [ "$1" = 0 ] ; then chkconfig qubes_core off chkconfig qubes_core_netvm off chkconfig qubes_core_appvm off - chkconfig qubes_firewall off - chkconfig qubes_netwatcher off + chkconfig qubes-firewall off + chkconfig qubes-netwatcher off fi %package systemd diff --git a/vm-init.d/qubes_firewall b/vm-init.d/qubes-firewall similarity index 100% rename from vm-init.d/qubes_firewall rename to vm-init.d/qubes-firewall diff --git a/vm-init.d/qubes_netwatcher b/vm-init.d/qubes-netwatcher similarity index 100% rename from vm-init.d/qubes_netwatcher rename to vm-init.d/qubes-netwatcher