From 5da7a520c4792fef77f25dd954236e1662d9e9ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sun, 1 Sep 2013 01:26:43 +0200 Subject: [PATCH] core: move pci_add/pci_remove to QubesVM, add support for live add/remove (#708) This additionally requires qubes.DetachPciDevice service in VM. --- core-modules/000QubesVm.py | 37 +++++++++++++++++++++++++++++++++++++ qvm-tools/qvm-pci | 13 ++----------- qvm-tools/qvm-prefs | 3 +++ 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/core-modules/000QubesVm.py b/core-modules/000QubesVm.py index 0b15f825..ddab54cf 100644 --- a/core-modules/000QubesVm.py +++ b/core-modules/000QubesVm.py @@ -1227,6 +1227,43 @@ class QubesVm(object): return conf + def pci_add(self, pci): + if not os.path.exists('/sys/bus/pci/devices/0000:%s' % pci): + raise QubesException("Invalid PCI device: %s" % pci) + if self.pcidevs.count(pci): + # already added + return + self.pcidevs.append(pci) + if self.is_running(): + try: + subprocess.check_call(['sudo', system_path["qubes_pciback_cmd"], pci]) + subprocess.check_call(['sudo', 'xl', 'pci-attach', str(self.xid), pci]) + except Exception as e: + print >>sys.stderr, "Failed to attach PCI device on the fly " \ + "(%s), changes will be seen after VM restart" % str(e) + + def pci_remove(self, pci): + if not self.pcidevs.count(pci): + # not attached + return + self.pcidevs.remove(pci) + if self.is_running(): + p = subprocess.Popen(['xl', 'pci-list', str(self.xid)], + stdout=subprocess.PIPE) + result = p.communicate() + m = re.search(r"^(\d+.\d+)\s+0000:%s$" % pci, result[0], flags=re.MULTILINE) + if not m: + print >>sys.stderr, "Device %s already detached" % pci + return + vmdev = m.group(1) + try: + self.run("QUBESRPC qubes.DetachPciDevice dom0", user="root", + localcmd="echo 00:%s" % vmdev, wait=True) + subprocess.check_call(['sudo', 'xl', 'pci-detach', str(self.xid), pci]) + except Exception as e: + print >>sys.stderr, "Failed to detach PCI device on the fly " \ + "(%s), changes will be seen after VM restart" % str(e) + def run(self, command, user = None, verbose = True, autostart = False, notify_function = None, passio = False, passio_popen = False, passio_stderr=False, ignore_stderr=False, localcmd = None, wait = False, gui = True): """command should be in form 'cmdline' When passio_popen=True, popen object with stdout connected to pipe. diff --git a/qvm-tools/qvm-pci b/qvm-tools/qvm-pci index a5a9a918..a9f19583 100755 --- a/qvm-tools/qvm-pci +++ b/qvm-tools/qvm-pci @@ -68,13 +68,7 @@ def main(): exit (1) pci = args[1] - if not os.path.exists('/sys/bus/pci/devices/0000:%s' % pci): - print >> sys.stderr, "Invalid PCI device: %s" % pci - exit(1) - if vm.pcidevs.count(pci) == 0: - vm.pcidevs.append(pci) - if vm.is_running(): - print >>sys.stderr, "NOTICE: Changes will be seen by VM after VM restart" + vm.pci_add(pci) qvm_collection.save() qvm_collection.unlock_db() @@ -84,10 +78,7 @@ def main(): exit (1) pci = args[1] - if vm.pcidevs.count(pci) > 0: - vm.pcidevs.remove(pci) - if vm.is_running(): - print >>sys.stderr, "NOTICE: Changes will be seen by VM after VM restart" + vm.pci_remove(pci) qvm_collection.save() qvm_collection.unlock_db() diff --git a/qvm-tools/qvm-prefs b/qvm-tools/qvm-prefs index 62888393..f5c59a38 100755 --- a/qvm-tools/qvm-prefs +++ b/qvm-tools/qvm-prefs @@ -173,6 +173,9 @@ def set_pcidevs(vms, vm, args): print >> sys.stderr, "Missing pcidevs argument!" exit (1) + if vm.is_running(): + print >>sys.stderr, "Cannot modify PCI devices of running VM, " \ + "use qvm-pci instead" vm.pcidevs = list(eval(args[0])) def set_netvm(vms, vm, args):