Przeglądaj źródła

Cloning a vm now clones persistent PCI device assignments

fixes QubesOS/qubes-issues#4992
Marta Marczykowska-Górecka 4 lat temu
rodzic
commit
c0a8c6528a
1 zmienionych plików z 21 dodań i 1 usunięć
  1. 21 1
      qubesadmin/app.py

+ 21 - 1
qubesadmin/app.py

@@ -38,6 +38,7 @@ import qubesadmin.storage
 import qubesadmin.utils
 import qubesadmin.vm
 import qubesadmin.config
+import qubesadmin.devices
 
 
 class VMCollection(object):
@@ -316,7 +317,9 @@ class QubesBase(qubesadmin.base.PropertyHolder):
         return self.domains[name]
 
     def clone_vm(self, src_vm, new_name, new_cls=None, pool=None, pools=None,
-                 ignore_errors=False, ignore_volumes=None):
+                 ignore_errors=False, ignore_volumes=None,
+                 ignore_devices=False):
+        # pylint: disable=too-many-statements
         """Clone Virtual Machine
 
         Example usage with custom storage pools:
@@ -337,6 +340,7 @@ class QubesBase(qubesadmin.base.PropertyHolder):
             logged, or abort the whole operation?
         :param list ignore_volumes: do not clone volumes on this list,
             like 'private' or 'root'
+        :param bool ignore_devices: if True, do not copy device assignments
 
         :return new VM object
         """
@@ -472,6 +476,22 @@ class QubesBase(qubesadmin.base.PropertyHolder):
             del self.domains[dst_vm.name]
             raise
 
+        if not ignore_devices:
+            try:
+                for devclass in src_vm.devices:
+                    for assignment in src_vm.devices[devclass].assignments(
+                            persistent=True):
+                        new_assignment = qubesadmin.devices.DeviceAssignment(
+                            backend_domain=assignment.backend_domain,
+                            ident=assignment.ident,
+                            options=assignment.options,
+                            persistent=assignment.persistent)
+                        dst_vm.devices[devclass].attach(new_assignment)
+            except qubesadmin.exc.QubesException:
+                if not ignore_errors:
+                    del self.domains[dst_vm.name]
+                    raise
+
         return dst_vm
 
     def qubesd_call(self, dest, method, arg=None, payload=None,